JavaScript Date function not working in Firefox - javascript

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);

Related

Using 0 to identify the last day of a month doesn't work globally

This javascript method for determining the last day of the month doesn't work for me, who is in Ukraine, but it works for my colleague in the US. I get 2022-10-30 and my colleague gets 2022-10-31. What is the problem?
var now = new Date();
const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).toISOString().split('T')[0];
console.log(lastDayOfMonth)
I created a codepen and we got different results:
Сodepen to check
It's because of timezones. new Date works in local time, but toISOString formats the UTC version of the date/time. You don't want to mix UTC methods and local methods, because you'll get inconsistent results. In this case, since you're ahead of UTC, your local date/time at midnight is on the previous day in UTC. But in the States, they're behind UTC (and not so far behind they have the opposite problem), so it works for them.
Start with midnight UTC instead, via the UTC method, so you're consistently using a single timezone:
const now = new Date();
const lastDayOfMonth = new Date(Date.UTC(now.getFullYear(), now.getMonth() + 1, 0))
.toISOString()
.split("T")[0];
console.log(lastDayOfMonth);

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));

Understanding JavaScript dates in British Summer Time

I live in the UK. If I create a date object for 1st June, I would have expected .getUTCDate() to return the "correct" day of the month as 1, but instead it returns 31 and .getDate(), which I thought was meant to return the locale date returns 1.
new Date(2020,5,1).getUTCDate() // 31
new Date(2020,5,1).getDate(); // 1
Why is this? Is it because new Date(2020,5,1) is already converted to local time or something? I thought dates were stored universally, and it is only when the date is printed out that the locale rules are applied? I've read all the MDN docs and still don't understand, I would really appreciate if someone can walk through the steps of what happens for the above to return 31 and 1.
A brief explanation of how ECMAScript Date constructor works.
Single string values are parsed and converted to Dates in weird and wonderful ways that are mostly implementation dependent, see below. So all of the following ignores parsing and assumes the Date constructor is called with at least two arguments, year and month. In this case, string values are converted to number as if by Number(value).
All the non–UTC methods work in local time, i.e. based on the host system date, time and timezone offset settings. When creating a Date object using the constructor and values for year, month, day, etc. then any missing values are treated as 0 except for the day, which defaults to 1.
So
new Date(2020, 5, 1)
creates a date based on the host (local) settings for date, time and timezone offset for that date and time, respecting historical changes like daylight saving and other adjustments (common before 1900) as if by:
new Date(2020, 5, 1, 0, 0, 0, 0); // Local 1 Jun 2020 00:00:00.000
So getUTCDate will return 31 (i.e. 31 May) for systems with a timezone offset that is less than zero and 1 (i.e. 1 Jun) for any with an offset of zero or greater. The largest positive offset in common use is +14 and the smallest is -10.
If you want to create a Date based on UTC values, then use the Date.UTC method, whcih returns a number, the time value, so you have to pass it to the Date constructor to create a Date object:
new Date(Date.UTC(2020, 5, 1)).getUTCDate(); // 1 regardless of host settings
Parsing strings: new Date(string) and Date.parse(string)
This where the Date object crashes and burns. While the constructor mostly uses local, it can also use UTC even where UTC is not specified. Parsing of strings is almost entirely implementation dependent except for the 3 formats supported by ECMA-262. Even the supported formats are not parsed consistently across implementations so the general advice is do not use the built–in parser. See Why does Date.parse give incorrect results?

JavaScript getting date string as 11pm on the day before

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)

Milliseconds for current date in javascript

When I try the following
new Date().valueOf()
the result is 140082670954. For
new Date('05/23/2014').valueOf()
the result is 1400783400000.
There is a difference in the millisecond outputs. The second one is at 00:00:00 hrs but the first one is at 12pm with todays date.
I need to get the milliseconds as in the second one. How would I do this dynamically?
When you do:
new Date()
a new Date object is created with a time value for the current instant. When you do:
new Date('05/23/2014')
a new Date object is created at 00:00:00.000 on the specified date. If you want the equivalent using the constructor, then create the Date and set the time appropriately:
var d = new Date();
d.setHours(0,0,0,0);
NB
Please don't pass strings to the Date constructor. It calls Date.parse which is largely implementation dependent and inconsistent across browsers (even using the string format specified in ES5). Call the constructor with the required values:
new Date(2014, 4, 23);
noting that months are zero indexed so May is 4.
I take it that you want the milliseconds from midnight of a given day? I am afraid it won't be too simple, thanks to JavaScript's very constrained date-time API. You can extract the year, month, and day from the date object and create a new object from those:
var now = new Date();
var day = now.getDate();
var month = now.getMonth();
var year = now.getFullYear();
var today = new Date(year, month, day);
var millis = today.valueOf();
BTW: You mention that the first one "is at 12pm" - that depends on at what time you execute the statement. new Date() gives you the date including the current local time. So it appears that you tried it at roughly 12pm :-)

Categories