8601 ISO String to readable date format in Javascript - javascript

I'm having a pretty horrid time trying to convert an 8601 into a readable format. The date shows as 'P0DT0H0M10S' and is stored in a var called timeLeft. Every article I find online tells me how to turn dates INTO the 8601 format, but not the other way around.
I tried using moment.js but that seems to revolve around the current date and not one set by my timeLeft var. How do I get this var into a user-friendly format? Thanks

Moment has a duration type:
var duration = moment.duration('P1Y2M3DT4H5M6S');
// user-friendly format
var out = duration.humanize();
snippet.log(out);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.1/moment.min.js"></script>
<script src="https://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

First off, that's not an ISO-8601 date (not even close).
Second, momentjs does support parsing a string into a moment, with the moment("20111031", "YYYYMMDD") syntax (from their front page examples).
I'm not sure what the pattern you need would be, but maybe something like [P]D[DT]H[H]M[M]S[S].

Related

When converting date, I get previous day

I want to convert a string into a date "as it is".
const date = "8/16/2019"
console.log(new Date(date))
However, I get:
As you can see I get the prevous day. I was thinking that it might be a timezone issue, even though there is no timezone that I am converting it from.
Any suggestions how to convert is as it is?
I appreciate you replies!
If your format is consistent, you could split on / and use Date.UTC. Creating your new Date from that would ensure it's UTC.
const date = "8/16/2019"
const [month,day,year] = date.split("/");
const utcDate = Date.UTC(year,month-1,day);
console.log(new Date(utcDate));
const date = "8/16/2019"
console.log(new Date(date).toLocaleString("en-US", {timeZone: "Asia/kolkata"}))
Note:- You need to add timezone
You can use toLocaleDateString
console.log(new Date("8/16/2019").toLocaleDateString('en-us', {timeZone: "Asia/Kolkata"}))
new Date("8/16/2019") will create a date object using your current timezone. Add a "Z" at the end if you want your date to be in UTC.
console.log(new Date("8/16/2019Z"))
EDIT
It appears that Firefox is not implementing the parsing of standard date format. Unfortunately until recently how exactly was a date parsed was completeley based on heuristics and intrinsically non portable.
Looking at Firefox bug tracker seems the issue has been discussed but the problem is still present (some toolkit just works around by replacing "Z" with "+00:00" before calling the parser).
The only way to be sure on every browser is to parse the string yourself and build the date from the fields. I didn't notice because I'm using chrome instead (in both chrome and Node works as expected).
EDIT 2
After more investigation seems the standard requires that:
If you use yyyy-mm-ddThh:mm:ssz then you get what ISO format for datetime defines it to be. Also the syntax described in the standard is not very precise and for example is not clear to me if the time zone can be present when no time is present (Chrome says yes, Firefox says no).
If you use another format then anything goes (so for example there is no string that is guaranteed to issue an invalid date response).
In other words new Date("8/16/2019") is not portable Javascript (with the meaning that you don't know what date / time / timezone you will get, if any). Either you parse yourself the date or you just live with what that version of that Javascript engine in that moment decides to give you.

Check if start datetime and end datetime are valid in momentjs

Im new to momentJs so I need a bit of help here. I am building a form where the user can send in their availabilities for a certain work period. So in the form you have a startDate, startTime, endDate and endTime. Due to the api that I have to use from a client we have to send the date like this (example) "2015-06-17T14:24:36" (with the 'T' in the middle). Currently I receive the date and the time seperate from eachother but merging them together in the end so it fits the api's way of reading date.
Now my question is as follow. I have to create a check where I can see if the input startdate-time and enddate-time are valid. For example the startdate always has to be a date BEFORE the end date (pretty logic right). But is there an easy way to do this in momentJS?
Or should I use another method?
Thanks in regard and if my question is not quite clear please let me know so I can provide extra information!
NOTE: in the end it should be something like this:
var start = "2017-06-17T14:24:36"
var end = "2017-07-03T14:24:36"
Function that checks if the start and end dates are valid
Result = true
If you simply have to check that startDate is before endDate you can use isAfter.
Here a working sample:
var start = "2017-06-17T14:24:36";
var end = "2017-07-03T14:24:36";
function checkDate(start, end){
var mStart = moment(start);
var mEnd = moment(end);
return mStart.isBefore(mEnd);
}
console.log(checkDate(start, end));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
In my first example I'm using moment(String) parsing that accepts input in ISO 8601 format.
If you need to parse non ISO 8601 format you can use moment(String, String) specifying input format (e.g. var mStart = moment(start, 'DD-MM-YYYYTHH:mm:ss');).
If you have to support multiple formats you can use moment(String, String[]). As docs states moment(String, String[]):
Prefer formats resulting in valid dates over invalid ones.
Prefer formats that parse more of the string than less and use more of the format than less, i.e. prefer stricter parsing.
Prefer formats earlier in the array than later.

Moment failing on some dates

Here are my dates, to me there is no different whatsoever. Yet moment can't handle them all:
console.info(details.date);
console.info(moment(details.date).format());
console.info('________________________________________');
result.date = moment(details.date, "DD-MM-YYYY H:m").format();
//Console
________________________________________
16/10/10 15:00
Invalid date
________________________________________
09/10/10 15:00
2010-09-10T15:00:00+01:00
How can I make my dates safe.
It appears Moment is using the American Date convention, despite it not being documented in there moment(string) interface.
A simple example is here
According to the documentation for moment(string), if a format is not provided when parsing a string it will first try to match one of the ISO 8601 formats specified in ECMA-262. Failing that, it will simply pass the string to new Date(string), which is the same as using Date.parse.
So the result is entirely implementation dependent. However, most browsers will treat nn/nn/nn as a US style date with two digit year, i.e. mm/dd/yy. But that is not guaranteed and may change from browser to browser.
The fix is to always pass the format when parsing strings.
In the second example, the format specified doesn't match the string supplied. It seems it falls back to Date.parse in this case also.
Your date format string uses hyphons ("-") and actual date uses slashes ("/"), so Moment.Js is unable to parse it. Works fine in following example
$("body").text(moment("16/10/10 15:00", "DD/MM/YY H:m").format())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.js"></script>

Strip Time Zone from a string using JavaScripty, Moment.js, etc?

Suppose I have a string like "01/22/2014 2:07:00 PM -08:00".
I want to
a) Format it in ISO 8601 with time offsets from UTC http://goo.gl/JTfAZq, so it becomes "2014-01-22T14:07:00-08:00"
b) Strip out time offset part so it becomes "01/22/2014 2:07:00 PM" [and then format it in ISO 8601 so it becomes "2014-01-22T14:07:00"]
Sure I can use JavaScript string functions (and regular expressions), but it seems to be a better approach to use JavaScript Date() object facilities or Moment.js. Neither work, however. Both automatically convert dates to a current system timezone (-05:00 for me), so 2:07 PM becomes 5:07 PM. I found two ways of doing that "strip out time offset then format" task, but both looks ugly and brittle:
var mydateTime = "01/22/2014 2:07:00 PM -08:00";
// strip out time offset part using substring() so that Moment.js
// would think time is specified in a current zone
var myNewDateTime1 = moment(mydateTime.substring(0, mydateTime.length - 7)).format("YYYY-MM-DDTHH:mm:ss")
// or probably even worse trick - strip out time offset part using format
var myNewDateTime2 = moment(mydateTime, "MM/DD/YYYY h:mm:ss A").format("YYYY-MM-DDTHH:mm:ss")
I understand that JavaScript Date() object is not designed to preserve a time zone, but doesn't more elegant and stable solution exist for a) and b) ?
I think you are looking for moment.ParseZone. It parses the moment AND preserves the time zone offset that was in the string, instead of converting it to the browser's local time zone.
Also, your myDateTime variable doesn't match what you were asking about. If you do indeed already have a full ISO8601 extended with time zone offfset, then it is like this:
var m = moment.parseZone("2014-01-22T14:07:00-08:00");
Or if it's like you originally, showed, then like this:
var m = moment("01/22/2014 2:07:00 PM -08:00",
"MM/DD/YYYY h:mm:ss A Z").parseZone();
From there, you can format it however you like:
var s = m.format("YYYY-MM-DDTHH:mm:ss");

Trying to parse date using new Date(). but keep getting wrong results

I am trying to parse a date string i get from php through ajax call(which is irrelevant for now) using new Date().
however i keep getting wrong results.
My string is 2013-05-09 20:56:17
When i do
var something = new Date("2013-05-09 20:56:17");
alert(something.getMonth());
It keeps alerting 0
In my opinion for some reason new date cant parse this string.
Is there a way to specify the date format for new Date() in JS ?
My current solution is to import php's: date() and strtotime() and use them :
alert(date('m', strtotime("2013-05-09 20:56:17")));
This works however I have to use external js lib and I am pretty sure there is a better JS way to achieve that.
If you use slashes instead of hyphens, it works:
var something = new Date("2013/05/09 20:56:17");
alert(something.getMonth());
It's easy enough to replace any hyphens in a string with slashes first if you need to (say, if you were getting the date string from somewhere else):
var something = new Date("2013-05-09 20:56:17");
something = something.replace('-', '/');
It seems JavaScript's Date constructor doesn't recognize date formats with hyphens, or at least not that particular format.
Choose a different format specifier in PHP for your ajax dates. The format you expect and the format expected by the javascript are different.
var something = new Date("2013-05-09T20:56:17");
Note the 'T' which appears as a literal separator and marks the beginning of time per ISO 8601
Reference for various [browser] javascript date formats
W3 DateTime
Microsoft IE DateTime
Mozilla [Firefox] DateTime
Google DateJs
And lastly, the PHP date format specifier list:
PHP Date
PHP DateTime
Note the 'DATE_ISO8601'; but I suggest not using that at this time. Instead use 'DATE_ATOM' which may produce a date format more widely supported (comments suggest it makes iPhones happier and no issues with other browsers).
To use it in PHP:
$something = new DateTime('NOW');
echo $something->format('c');
echo $something->format(DateTime::ATOM);

Categories

Resources