JavaScript getting date string as 11pm on the day before - javascript

I have the following input field:
In my web app I have -
string date - 06/05/2018
And this JS code:
var d = "06/05/2018".split("/");
var date = new Date(d[2] + "-" + d[1] + "/" + d[0]).getTime();
console.log(date)
This returns 1525561200000 which if I put that into epoch converter gives me...
Saturday, May 5, 2018 11:00:00 PM
This then screws up with my filtering system - date ranges because if I select the minimum date to be 06/05/2018 with the input field:
var d = $('#min').val()
var date = new Date(d).getTime();
console.log(date)
It is returning 1525564800000 which comes to Sunday, May 6, 2018 12:00:00 AM
How do I get around this?
Thanks

I could write an entire thesis on how problematic and difficult it is to work with dates in Javascript and how to avoid pitfalls and weird bugs, but in the end your specific problem comes down to a simple typo.
The string you're parsing manually and passing to the Date constructor looks like this:
2018-05/06
You've mistakenly used a / instead of a - as the second delimiter when concatenating the string. For some reason, the browser then creates the date object as midnight 2018-05-06 local time. When passing in the string in the standard format (which is what happens when taking it from the date input), i.e. 2018-05-06, the date object gets created as midnight 2018-05-06 UTC time.
So, in short, your problem can be solved by replacing the "/" with "-" in your string concatenation and the two dates should be the same.
However, I should point out that passing a string to the Date constructor is unreliable since the result is not standardized and may differ between browsers (which is also why it behaves so unpredictable and seemingly illogical in this case). It's a better idea to pass numbers instead since the specification dictates the result of that. You're already halfway there since you've split the date string into its components. Try this:
var date = new Date(
Number(d[2]),
Number(d[1]) - 1, // Subtracting 1 from month since it's base 0
Number(d[0])
).getTime();
(Technically, we don't even need to explicitly convert to Number since the Date constructor expects all arguments to be numbers when there's more than one argument and will convert whatever it gets into numbers internally)

Related

Creating timezone independent dates in Javascript?

This question is related to this question.
So if we construct a date using an ISO string like this:
new Date("2000-01-01")
Depending on what timezone we are in, we might get a different year and day.
I need to be able to construct dates in Javascript that that always have the correct year, day, and month indicated in a string like 2000-01-01, and based on the answer in one of the questions if we use back slashes instead like this:
const d = new Date("2000/01/01")
Then we will always get the right year, day, and month when using the corresponding date API methods like this:
d2.getDate();
d2.getDay();
d2.getMonth();
d2.getFullYear();
So I just wanted to verify that my understanding is correct?
Ultimately I need to be able to create Date instances like this for example:
const d3 = new Date('2010/01/01');
d3.setHours(0, 0, 0, 0);
And the time components should always be zero, and the year, month, and day should be the numbers specified in the string.
Thoughts?
I just did a quick test with this:
https://stackblitz.com/edit/typescript-eztrai
const date = new Date('2000/01/01');
console.log(`The day is ${date.getDate()}`);
const date1 = new Date('2000-01-01');
console.log(`The day is ${date1.getDate()}`);
And it logs this:
The day is 1
The day is 31
So it seems like using backslashes should work ...
Or perhaps using the year, month (0 based index), and day constructor values like this:
const date3 = new Date(2000, 0, 1);
date3.setHours(0, 0, 0, 0);
console.log(`The day is ${date3.getDate()}`);
console.log(`The date string is ${date3.toDateString()}`);
console.log(`The ISO string is ${date3.toISOString()}`);
console.log(`Get month ${date3.getMonth()} `);
console.log(`Get year ${date3.getFullYear()} `);
console.log(`Get day ${date3.getDate()} `);
NOTE
Runar mentioned something really important in the accepted answer comments. To get consistent results when using the Javascript Date API use methods like getUTCDate(). Which will give us 1 if the date string is 2000-01-01. The getDate() method could give us a different number ...
From the ECMA standard of the Date.parse method:
When the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.
What is happening is that New Date() implicitly calls Date.parse on the string. The "2000-01-01" version conforms to a Date Time String Format with a missing offset representation, so it is assumed you mean UTC.
When you use "2000/01/01" as input the standard has this to say:
If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
So in short the browser can do what they want. And in your case it assumes you mean the offset of the local time, so whichever offset you are located in gets added when you convert to UTC.
For consistent results, perhaps you want to take a look at Date.UTC
new Date(Date.UTC(2000, 0, 1))
If you need to pass in an ISO string make sure you include the time offset of +00:00 (is often abbreviated with z)
new Date("2000-01-01T00:00:00Z");
If you want to later set the date to something different, use an equivalent UTC setter method (e.g. setUTCHours).
When you retrieve the date, also make sure to use the UTC getter methods (e.g. getUTCMonth).
const date = new Date("2000-01-01T00:00:00Z");
console.log(date.getUTCDate());
console.log(date.getUTCMonth());
console.log(date.getUTCFullYear());
If you want to retrieve the date in a specific format you can take a look at Intl.DatTimeFormat, just remember to pass in timeZone: "UTC" to the options.
const date = new Date("2000-01-01T00:00:00Z");
const dateTimeFormat =
new Intl.DateTimeFormat("en-GB", { timeZone: "UTC" });
console.log(dateTimeFormat.format(date));

Issues parsing a string-date React/JS

For example, I have this string "2020-09-09T21:00:14.114-04:00"
I grab this from my database and in its current form, it is a string. my goal is to have it display
4 PM instead of the long string of jibberish
is it possible to accomplish this?
I was thinking of possibly creating a new date object like
let test = new Date('2020-09-09T21:00:14.114-04:00').
but I'm stuck at the parsing and formatting part. it would be better to have this be done while the current state is a string but I don't think that this would be possible
edit: i would like the desired output to be the hour:minute and then am/pm
ex 10:15pm
You can do that by parsing the date from your database using Date.parse().
Then you can get the time or whatever you need using date.toLocalTimeString() in your case.
let dateUnix = Date.parse('2020-09-09T21:00:14.114-04:00');
const time = new Date(dateUnix).toLocaleTimeString();
console.log(time); // --> "4:00:14 AM"
The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognized or, in some cases, contains illegal date values (e.g. 2015-02-31).
Here's some useful resources MDN Date.parse()
MDN Date.toLocalTimeString()
You can do as following way.new Date() is used to get the current date and time.
var today = new Date();
var time = today.getHours();
if(time>12){
var new_time= time % 12;
}
else{
var new_time= time;
}

When is the month in a Date-object zero indexed

I know, because zero indexed month, for the date
Thu Mar 02 2017
I have to write
new Date(2017, 2, 2);
The same if I use a variable
var thismonth = 2; new Date(2017, thismonth, 2);
But, if I say
var thisday = [2017, 2, 2]; new Date(thisday);
I get a result with a one indexed month
Thu Feb 02 2017
This means, I can use the array-vars like the date-vars in the real life
var thisday = [2017, 3, 2]; new Date(thisday);
and get the (un)expected result
Thu Mar 02 2017
Thats nice, but confusing! Why this behaviour? Is there a rule?
That's an interesting find! However there is no documented Date constructor that accepts an array of values such as [2017, 3, 2], so what you are getting in this case isn't something you should rely on.
You can see that among your examples, only the first one is documented:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date
I don't think the code does what you think it does. The Date constructor does not accept arrays. Quoting the spec
Let v be ? ToPrimitive(value).
If Type(v) is String, then
Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (20.3.3.2). If the parse resulted in an abrupt completion, tv is the Completion Record.
which means you actually pass 2017,3,2 as a string. Now what happens to that string? Well, check the spec again.
Otherwise, parse interprets the resulting String as a date and time; it returns a Number, the UTC time value corresponding to the date and time. The String may be interpreted as a local time, a UTC time, or a time in some other time zone, depending on the contents of the String. The function first attempts to parse the format of the String according to the rules (including extended years) called out in Date Time String Format (20.3.1.16).
Interesting, another link to the spec
Your format doesn't follow the YYYY-MM-DDTHH:mm:ss.sssZ format or date only YYYY-MM-DD which means we're back to the previous spec section which says
If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
So basically you should not rely on it. Depending on the JS engine/browser the date might not be parsed at all. It looks like V8 accepts not only colons/dashes as separators, but also commas, which is why it works.
Edit: found it
https://github.com/v8/v8/blob/68960eeb763f93dcedb37d5b663b1019192b7f36/src/builtins/builtins-date.cc#L115
which calls
https://github.com/v8/v8/blob/68960eeb763f93dcedb37d5b663b1019192b7f36/src/dateparser-inl.h#L16
which has plenty of comments and weird stuff to keep searching if you want.

JavaScript Date function not working in Firefox

I have this code and I run it in chrome
var time = new Date("2014-02-11 19:30:00" + ' UTC');
This gives me back exactly what I need, it transforms the date I'm passing to my local time. Even this one does the exact same thing
var time = new Date("2014-02-11T19:30:00");
The problem is that the first function is not working in Mozilla and the second one doesn't transform the date to my local timezone. I need to do the transformation in both explorers (actually in all of them) but it would be great for it to at least work in those two.
This should work on both:
Note: TZD = time zone designator (Z or +hh:mm or -hh:mm)
new Date("1994-11-05T13:15:30Z")
Creates a JavaScript Date instance that represents a single moment in time. Date objects are based on a time value that is the number of milliseconds since 1 January, 1970 UTC.
Constructor
new Date();
new Date(value);
new Date(dateString);
new Date(year, month [, day, hour, minute, second, millisecond]);
It is the definition of the Date object to use values 0-11 for the month field.
I believe that the constructor using a String is system-dependent (not to mention locale/timezone dependent) so you are probably better off using the constructor where you specify year/month/day as seperate parameters.
BTW, in Firefox,
new Date("04/02/2008");
works fine for me - it will interpret slashes, but not hyphens. I think this proves my point that using a String to construct a Date object is problemsome. Use explicit values for month/day/year instead:
new Date(2008, 3, 2);

Convert DateTime string to timestap in javascript

if dd = "2012-08-20 01:16:00";
converting this date to time-stamp (as in the following code)
var t = new Date(dd).getTime();
http://jsfiddle.net/userdude/DHxwR/
the result t = NaN why ?
According to ECMA-262 (§15.9.1.15, Date Time String Format, page 169), the only date string format required to be accepted is:
[+YY]YYYY[-MM[-DD]][THH:mm[:ss[.sss]]]Z
where Z is either Z (for UTC) or an offset consisting of either a + or a - followed by HH:mm. Any other formats that happen to be supported by a particular browser should not be relied upon, as continued support is not guaranteed.
Therefore, replace the space with a T and append either a Z, or a fixed time zone offset before passing it to the Date constructor. For example, if the date and time are in the UTC+8 zone:
var dd = "2012-08-20 01:16:00";
var t = new Date(dd.replace(' ', 'T') + '+08:00').getTime();
This will return the number of milliseconds from January 1, 1970, midnight UTC, to the date you have specified, treated as either universal time (if you appended Z) or a time local to the fixed time zone offset that you specify.
Please note that this will act differently in that the date is not simply treated as time local to the user's system time zone as your question's example does. However, I can't think of a situation where doing that would be useful, because you'd get different results depending on the user's configuration — but in reality, the time difference between two dates is always the same no matter where you are.
Try to use a space or comma between the year, month, and day values.
It's simple:
+(new Date("2012-08-20 01:16:00"));

Categories