javascript create date without daylight savings conversion - javascript

when i create date using date constructor new Date('2015','12'), it results in Fri Jan 01 2016 00:00:00 GMT-0500 (Eastern Standard Time). But don't it to assume that what date i am providing is already applied daylight conversion and create date object for december 2015, instead of jan 2016

When creating a date using the Date constructor, the time zone of the host system is almost always used (per ECMA-262). The only exception is when a number (interpreted as a time value, i.e. milliseconds since the ECMAScript epoch) is provided, or an ISO 8601 format string with a time zone. Even then, the internal time value of the Date (i.e. milliseconds since the epoch) is calculated in UTC and the host system time zone offset used for the non–UTC methods like getHours, getMinutes, etc.
Also, the timezone offset of the current systems settings are used for historical dates. So if the host is set for daylight saving, it will be applied to dates at times before daylight saving was implemented. Also, historical changes to daylight saving changeover dates and times (and even value) are not applied. The currents settings are assumed to always apply for past and future dates.
So all of the following will apply the timezone offset of the host system when creating a date for 3 February, 2016:
new Date('2/3/2016'); // US format is assumed by most browsers.
// May also create an invalid Date
new Date(2016, 1, 3); // months are zero indexed so 1 is February
new Date('2016-02-03T00:00:00'); // note missing time zone
However, the following will be treated as UTC (or invalid):
new Date('2016-02-03'); // contrary to ISO 8601, missing time zone for this
// format only is assumed to be UTC
new Date('2016-02-03T00:00:00Z'); // Note has a time zone of GMT
If you want to reliably create a Date for a specific instant in time from a string, you must provide a string with the time zone offset. Then parse it yourself since parsing of date strings is largely implementation dependent and varies across implementations. The best format to use is ISO 8601 extended so something like:
'2016-02-03T00:00:00-0800'
which represents the same instant in time no matter what the settings of the host system are. You just need to reliably parse it.
There are many good libraries for parsing and formatting, or you can write your own small functions for particular parse and output formats.

Related

How to convert a Date in specific Timezone and send to server

My scenario is a Date object created using the browser timezone (just using new Date()) and sent to the server, but I want to send this date with another specific timezone let's assume it's, Europe/Athens.
What would be the best representation of the actual date string so I can convert it back to a Date object in the backend in the actual Europe/Athens date?
I have the timezone info but not sure how to get a Fri Feb 05 2021 05:30:00 GMT-0500 (Eastern Standard Time) and convert it to Europe/Athens date.
I have tried to use date-fns but didn't get far.
You've got a few different questions and misconceptions, so I will attempt to address each of them, starting with question in the title:
How to convert a Date in specific Timezone and send to server
If you mean a date like 2021-01-18, that cannot be in a particular time zone. It is, by definition, just a date. Think about a printed calendar you might hang on your wall that has a square for each date. There are no time zones associated with such calendars. One can ask "what date is it now in a particular time zone", but the answer itself has no time zone.
If instead you meant a JavaScript Date object, the answer is again "you can't". The Date object is not actually a date, nor does it have a time zone, but rather it is a timestamp. Internally, a Date object only holds one value - the number of milliseconds that have elapsed since 1970-01-01 00:00:00.000 UTC (not considering leap seconds). It has no time zone. Instead, some functions such as .toString() will apply the system-local time zone while operating. That time zone comes from the operating system (in most cases). It is not stored inside the Date object itself.
My scenario is a Date object created using the browser timezone (just using new Date()) ...
That will use the system clock where the browser is running, but the time zone is not relevant. The Date object will be constructed from the Unix timestamp that represents "now". Such timestamps are inherently UTC based. The browser fetches the UTC time directly from the operating system, without considering time zone.
... and sent to the server
One cannot send an object to a server without going through deserialization on one side and serialization on the other.
... but I want to send this date with another specific timezone let's assume it's, Europe/Athens.
What would be the best representation of the actual date string so I can convert it back to a Date object in the backend in the actual Europe/Athens date?
Since the object only represents "now", you don't need to send it in a time zone specific format. Just send the UTC time. The ideal format is ISO 8601, which can be obtained directly using the .toISOString() function from the Date object.
Depending on your use case, you might also consider whether you might instead just take the UTC time from the server instead. At least you will have some control over the clock.
On the server side, if you need the time in a specific time zone, then convert from UTC to that time zone on the server, not on the client.
Also, from comments:
I believe even EPOCH is different between timezones. I could just get the EPOCh and then try to work with converting to specific timezones.
That is incorrect on a few levels. First, understand that epoch is just an English word meaning essentially "a representation of a starting point". It isn't a format, nor is it an acronym. In JavaScript, Date objects use Unix timestamps, which use an epoch of 1970-01-01T00:00:00.000Z. In other words, Midnight Jan 1st 1970 UTC is the 0 timestamp. Sometimes, such timestamps are referred to as "epoch time". That's a misnomer in my opinion, but even still - they are always UTC based. There is no time zone, and thus they are the same for the whole world.
Try to use toLocaleString:
let date = (new Date()).toLocaleString("en-US", {timeZone: "Europe/Athens"});

Ambiguous behavior of javascript new Date() constructor for same different formatted string

My local time zone is (UTC+06:00) Dhaka. In my own time zone I didn't find this problem. But changing the time zone to (UTC -12:00) International Date Line West in my pc,
new Date(["2014","01","01"]) is giving me output Wed Jan 01 2014 00:00:00 GMT-1200 (GMT-12:00).
new Date("2014-01-01") is giving me output Tue Dec 31 2013 12:00:00 GMT-1200 (GMT-12:00).
Why this is happening?
Shouldn't ["2014","01","01"] and "2014-01-01" suppose to give same output?
This is due to new Date("2014-01-01") being created through the Date parse which considers this date to be UTC and then apply the timezone but new Date(["2014","01","01"]) is treated as literal values for each of the parameters in the constructor for your timezone. Although as mentioned in one of the comments below the format new Date(["2014","01","01"]) does not conform to RFC and hence provides different results depending on the browser.
from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
Note: Parsing of date strings with the Date constructor (and Date.parse(), which works the same way) is strongly discouraged due to browser differences and inconsistencies. Support for RFC 2822 format strings is by convention only. Support for ISO 8601 formats differs in that date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
Perhaps what you are after is new Date(Date.UTC(2014,01,01)); Date.UTC in order to create a consistent date that is not bound to the user's configuration.
A few things:
The Date constructor does not accept an array. See the specification, and the MDN docs. Any such allowance is implementation-specific. For example, new Date(["2014","01","01"]) will work in Chrome because the Chrome authors decided to allow it, but in Edge it gives an Invalid Date because it is not required by the specification. (The same applies to Date.UTC(array).)
If you have separate date parts, you should pass them directly into the constructor. Note that in this form of the constructor, the months range from 0 to 11, so you must subtract one from the second parameter.
new Date(2014, 0, 1)
When you use the above form, the parameters are intended to be in terms of local time - that is, the time zone that is set for the environment where the code executes (the user's time zone in a browser environment, or the server's time zone in a Node.js environment). The time parameters (hour, minute, second, millisecond) default to 0, so this is midnight in the local time zone, or 2014-01-01T00:00:00.000.
If you intended to pass UTC-based parameters, use the Date.UTC function, and pass the result back to the Date constructor, as in:
new Date(Date.UTC(2014, 0, 1))
This sets the date object to midnight UTC, or 2014-01-01T00:00:00.000Z.
When you pass a string to the date constructor, it is first attempted to be parsed according to rules defined in the specification. If it cannot be parsed by the specification's rules, then it may be parsed in an implementation-specific manner.
The specification defines that a string in YYYY-MM-DD format (without any time portion) is to be parsed as UTC. This deviates from ISO-8601, and is why you are seeing different results when you call new Date("2014-01-01"). It is interpreted as if you passed 2014-01-01T00:00:00.000Z (UTC).
The Date object itself tracks only one single value, which is the number of milliseconds since the Unix epoch, which is 1970-01-01T00:00:00.000Z (UTC). You can see this value by calling .valueOf() or .getTime(). Thus when you parse with any form that is treated as local time, then a conversion happens at the time of parsing, from local time to UTC.
Later, when you do anything that expects local time output, such as calling .toString(), or using functions like .getDate(), .getHours(), etc., another conversion from the internal UTC-based timestamp to local time is performed.
In some environments, you will also see the conversion happen when you console.log a Date object, as if you called .toString(). In others, you will see the UTC-based output as if you called .toISOString(). The console output is implementation-specific.
Notice that GMT time is -1200. When you are specifying the date, I believe it starts at midnight of that day. Since you stated 2014-01-01, it subtracted 12 hours from midnight on that day, giving you 2013-12-31 at 12:00PM.

Date.parse not working [duplicate]

This question already has answers here:
Why does Date.parse give incorrect results?
(11 answers)
Closed 6 years ago.
In javascript I tried this
new Date(Date.parse("2016-12-15"));
And it outputs a date object but with the date as Wed Dec 14 19:00:00 EST 2016. Why is it dec 14 when I expect it as dec 15?
Thanks
JavaScript dates don't contain a time zone. The date you are parsing is interpreted as December 15, 2016 at midnight UTC.
When you are converting it back to a string, it uses the time zone from your browser locale, and since you appear to be on the american east coast, the appropriate time zone is EST.
7pm EST equals midnight the next day in UTC.
Parse is not a reliable way to parse your date...
Differences in assumed time zone
Given a date string of "March 7, 2014", parse() assumes a local time
zone, but given an ISO format such as "2014-03-07" it will assume a
time zone of UTC (ES5 and ECMAScript 2015). Therefore Date objects
produced using those strings may represent different moments in time
depending on the version of ECMAScript supported unless the system is
set with a local time zone of UTC. This means that two date strings
that appear equivalent may result in two different values depending on
the format of the string that is being converted.
-- Source --
I think you should get the client date with its timezone and use a library like Moment.js to parse the date correctly.
You can create a date object from a specific UTC time using .Date.UTC() method, but then you have to pass the values individually:
new Date(Date.UTC(year, month, day, hour, minute, second));
A better and safer approach would be to use moment.js

Consistent Client Side Date/timestamp using JavaScript(considering TimeZones)

My question is regarding this quote from the manual about dates in JavaScript:
Note: parsing of date strings with the Date constructor (and
Date.parse, they are equivalent) is strongly discouraged due to
browser differences and inconsistencies.
new Date('2016-04-14') output for a user was Wed Apr 13 2016 17:00:00 GMT-0700 (US Mountain Standard Time) upon which he had to use .toUTCString().
How to handle this if the users are in many different time zones?
new Date().getTime(); returns an integer value as the time on client's machine since 1970 Jan 1.
Since this is an integer value, it will be agnostic of locales, browser version, different browsers (IE, Chrome, Mozilla, or anything).
So, this should give you consistent results in terms of time on client's machine as long as client's timezone is known.
You can fetch client's timezone offset by using getTimezoneOffset API
var x = new Date();
var currentTimeZoneOffsetInHours = x.getTimezoneOffset() / 60;
This together with new Date().getTime(); should give you consistent results.
If you use
new Date().getTime();
it will return you a milisecond time stamp since 1970-01-01 for the current time zone that the client is in. This can then be converted back to a date in any language.
This would be a better standard way to pass the date around if you are sending it to and from servers and between clients. As millisecond timestamp ts converted in timezone a will convert to 01/01/2010 and in timezone b will convert to 01/01/2010 as they are taken from 1970-01-01
Hope this makes sence

JavaScript date-only format guaranteed to be interpreted as local time in modern browsers

I am looking for a date format (only year, month and day, no time component), that will be guaranteed to be interpreted as local time, in all reasonably modern browsers, when passed to the Date() constructor in JavaScript.
The (3-letter English month abbreviation) (2-digit date) (4-digit year) format seems to work. When I do new Date('Apr 01 2015') on my English system, in Chrome, with my machine being in the Eastern timezone, I get back Wed Apr 01 2015 00:00:00 GMT-0400 (Eastern Daylight Time) which is exactly what I want.
However, I am not sure if this (3-letter English month abbreviation) (2-digit date) (4-digit year) format is guaranteed to be interpreted in the same way regardless of browser and browser/OS locale/language.
Will this format work the same way across different (reasonably modern) browsers and locales? If not, then is there some other format that will work?
Please note that ISO-8601 doesn't answer this question. ISO-8601 date-only strings are interpreted as being in UTC, and not in local time, so new Date('2015-04-01') is interpreted as Tue Mar 31 2015 20:00:00 GMT-0400 (Eastern Daylight Time), i.e. April 1 turns into March 31, which is not what I'm looking for.
I am looking for a date format (only year, month and day, no time component), that will be guaranteed to be interpreted as local time, in all reasonably modern browsers, when passed to the Date() constructor in JavaScript.
There isn't one. There are a number of formats that, in practice, are reliably parsed by all browsers in use however none of them are required by ECMA-262 to be supported by ECMAScript implementations.
There is one format, a version of ISO 8601, that is specified in ES5 and ECMAScript 2015 however dates without a time zone are to be treated as UTC in ES5 and "local" in ECMAScript 2015.
But that was seen by implementers as "breaking the web", so while some browsers implemented that for a while, they have now reverted to ES5 behaviour and treat a missing timezone as UTC.
A small change in format such as changing the separator from "-" to "/" causes a reversion to implementation dependent behaviour and may cause the date to be treated as UTC or local (though most seem to treat 2015/12/17 as local).
So if you want a guarantee, there isn't one. However, if you are prepared to write a 2 line function, you can parse an ISO 8601 like string reliably based on whatever time zone you like. If you want it to be treated as local (i.e. set to 00:00:00 and offset based on system settings), then:
function parseISOLike(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]-1, b[2])
}
document.write(parseISOLike('2015-12-17'));
will do the job (without checking for valid values) and allow the separator to be any non–digit, so 2015/12/17, 2015-12-17 and 2015.12.17 will all be correctly parsed.
Edit
Parts of the above have been edited thanks to input from Matt Johnson.

Categories