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

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

Related

is javascript new Date() created at same time on 2 diff machines/timezones exactly same?

I wanted to know if a date object created at any point of time differ based on time zones or not. I tried this by executing new Date().getTime() once for IST and immediately again by setting my PC time zone to GMT. The resultant values are:
IST - 1633334780053
GMT - 1633334788831
A difference of around 8000 milliseconds
From this it seems that datetime objects created at same moment are exactly same no matter in which time zone they are created. Please suggest if this understanding is correct or is there more to it.
You're right. Two different date time objects created at the same point of time are same no matter the time zone.
They can be formatted to their corresponding timezone representation using javascript.
One important thing to be noted is that the date time object created uses the system's date time configuration to find the correct time. If the system's date and time configurations are correct and in sync, then the date time object created in the browser will be correct and will match the system time at the time of creating that object.
This is detailed in the JavaScript specification: https://tc39.es/ecma262/#sec-date-objects.
More information is in the MDN docs Date.getTime():
The getTime() method returns the number of milliseconds* since the Unix Epoch.
*JavaScript uses milliseconds as the unit of measurement, whereas Unix Time is in seconds.
getTime() always uses UTC for time representation. For example, a client browser in one timezone, getTime() will be the same as a client browser in any other timezone.
So new Date().getTime() will always return the number of milliseconds since 1970-01-01 00:00:00 UTC, regardless of the client / machine timezone setting.

How to convert timespan using offset

I have MVC web application. I am storing UTC time in database. (Not datetime but just a time). In C# When I retrieve this time from the database I get timespan object back. I also have offset available in minutes. For example.
double offset = 600;
How do I use this offset to convert timespan to local datetime.
Note I don't want to use DateTime.ToLocalTime () method because that will use server's timezone.
UPDATE1
I am using the Javascript new Date().getTimezoneOffset() method to get the client's offset, and i have offset value stored on the server. Then I also have drop down list that show times as 12:00 AM, 12.30 AM, 1:00 AM etc etc. The dropdownlist is bound to model property SelectedDateTime of type DateTime. Idea is to convert user selected time to UTC and then UTC to localtime based on the offset. So lets say i have offset 300 minitues that would be 300/60 = 5 hours
double offset = 5.00; // this is available on the server
When the user selects time in a drop down list, I am getting a datetime object on the server, ignoring the date part i want to store UTC time into database. This is how I'm converting to UTC time.
TimeSpan utcTime = SelectedDateTime.AddHours(offset).TimeOfday;
I store this utcTime into the database. Now I want to convert UTC timespan into the client's datetime.
I am assuming i have Subtract offset now
var newLocalTimeSpan = utcTime.Subtract(TimeSpan.FromHours(offset));
var newLocalDateTime = new DateTime(newLocalTimeSpan.Ticks, DateTimeKind.Local);
However this throws the error:
Ticks must be between DateTime.MinValue.Ticks and
DateTime.MaxValue.Ticks.\r\nParameter name: ticks
For example with offest 5 hours, If user selects 8:00 PM then it will be converted to UTC and will be stored as 01:00:00.0000000 in database. When I retrieve the UTC value from database its '1:00:00 AM'. Then I subtract 5 hours form this TimeSpan which equals to `-4' now and if I pass Ticks to DateTime..i get above error.
NOTES: If you are curious why model property is DateTime instead of TimeSpan thats because i am using Kendo TimePicker which needs DateTime type.
UPDATE 2
I really appreciate all for your help. I have gone through all the articles #Matt Johnson has posted and it looks like I should not be using offset for calculating the UTC time. Mainly because of the day light time saving. But instead I should be using timezone. So I have 3 options here to find client’s time zone:
1> Use JavaScript to detect time zone
In JavaScript I can do new Date().toString() which returns date time as Sun May 22 2016 02:12:36 GMT-0500 (Central Daylight Time) I can then parse the string to get “Central Daylight Time” and post it to the server. However on server, for .net “Central Daylight Time” is not a valid windows time zone ID.
Question
Is this correct approach? Is JavaScript returning IANA zone id? Will it always return IANA zone id?
If JavaScript is returning IANA Id then I can use Matt’s article here to get windows time zone id
2> Use http://momentjs.com/ to detect client’s time zone
Question
Is momentjs returns IANA zone id?
If momentjs return IANA zone id then I can use Matt’s article above to get windows zone id. One of the reason I don’t like this approach is because I have to use 2 third party libraries momentjs and Noda Time
3> Provide user a drop down list using TimeZoneInfo.GetSystemTimeZones() and let the user selects the timezone.
User will select a time and timezone, then on server I will convert it to UTC using selected timezone and save it DB. However I have to show that time on some other pages, So I again need timezone. That means I have to put the drop down list in such a place on UI where it will be available all the time. Like top menu.
(I can certainly save timezone into DB along with the time, however if user travel to other place he will still see time in initially selected time zone. Which I don’t want)
Are these correct approaches? Am i missing something?
Question
Assume that I implement timezone selection using one of the approach above and i have correct client's time zone with windows timezone id on server in some variable.
Now lets say user selects 6:00 PM (Central Daylight Time , UTC -5) which will convert to UTC as 23:00:00. As long we are in Central Daylight Time the conversion from UTC to local will show 6:00 PM. Once we go into Central Standard Time which is UTC -6 Will the conversion still show 6:00 PM or 5:00 PM?
I am planning to use TimeZoneInfo.ConvertFromUtc(datetimevalue, timezone) method for converting UTC to Local
In general, there are only two viable approaches:
Pass only UTC dates and times to the client, and do all conversions to local time in the browser using JavaScript.
Use this approach when you don't care what the time zone actually is, but you just want it to match the browser's local time.
The Date object can do this, but you may find it easier to use a library such as moment.js, which gives you better control of output format, among other things.
Apply a time zone (not just an offset) to the UTC date and time on the server side, to produce the correct local time value.
Use this approach when the time zone affects an entire application, and needs to be known in server-side business logic.
You can try to guess the user's time zone using jsTimeZoneDetect or moment.tz.guess() in moment-timezone. However, it's just a guess, and it is always an IANA time zone ID (such as America/Los_Angeles).
Asking the user for their time zone from a list is a good idea. Usually one would place this on a user settings or profile page. You can use the guess made earlier to pick a default value from the list.
You will indeed need to use Noda Time on the server if you are using IANA time zones on the client.
Some applications choose to list Windows time zones instead, which is a much simpler approach as you can get everything from the TimeZoneInfo class. However, recognize that there are limitations with this approach including:
Localization issues, as you cannot easily get at display name strings other than the ones matching the operating system's default language, not .NET's globalization and localization features.
Maintainability issues, as you yield control to the operating system for keeping the time zone data updated. This may seem more convenient, but you may find that your hands are tied when keeping up with short-notice time zone changes. This is especially problematic when you don't have control over how or when updates are applied to the OS, such as with Microsoft Azure App Service.
Compatibility issues, as Windows time zones aren't generally recognized outside of Windows. If you ever expose the user's time zone setting in an API, you'll likely have translation issues for callers from other platforms.
Now, getting to your specific points:
I am using javascript new Date().getTimezoneOffset() method to get the client's offset...
That gives you the client's current offset. You have no guarantees that it is the correct time zone to apply for an arbitrary date and time.
If wanted to apply a fixed offset to a UTC DateTime in C#, the best way is with a DateTimeOffset.
DateTime utc = new DateTime(2016, 12, 31, 0, 0, 0, DateTimeKind.Utc);
DateTimeOffset dto = new DateTimeOffset(utc); // DateTimeKind matters here
TimeSpan offset = TimeSpan.FromMinutes(-300); // The offset is inverse of JavaScript's
DateTimeOffset result = dto.ToOffset(offset);
But do note this is only for a fixed time zone offset. For a true time zone, you would use the TimeZoneInfo class if you're using Windows time zones, or you would use NodaTime's DateTimeZone class for IANA time zones.
In JavaScript I can do new Date().toString() which returns date time as Sun May 22 2016 02:12:36 GMT-0500 (Central Daylight Time) I can then parse the string to get "Central Daylight Time" and post it to the server.
No, this approach is not recommended, for several reasons:
There's no guarantee you will get output in any particular format from JavaScript's toString function. The results are implementation specific, and will vary across browsers and platforms.
They are generally intended for display purposes. When DST is in effect, they'll show a daylight name, and when standard time is in effect they'll show a standard name.
They are often localized for the user's language, English, French, Chinese, etc.
The only native API that can return the user's time zone is:
Intl.DateTimeFormat().resolvedOptions().timeZone
This is part of the ECMAScript Internationalization API. Unfortunately, it currently only works in a handful of browsers. Both jsTimeZoneDetect and moment.tz.guess() will use this API if it's available, then will fall back to their own guessing logic if not.
Assume that i implement timezone selection using one of the approach above and i have correct client's time zone with windows timezone id on server in some variable. Now lets say user selects 6:00 PM (Central Daylight Time , UTC -5) which will convert to UTC as 23:00:00. As long we are in Central Daylight Time the conversion from UTC to local will show 6:00 PM. Once we go into Central Standard Time which is UTC -6 Will the conversion still show 6:00 PM or 5:00 PM?
I am planning to use TimeZoneInfo.ConvertFromUtc(datetimevalue, timezone) method for converting UTC to Local
As you said earlier, "Central Daylight Time" is not a valid Windows time zone identifier. Your user wouldn't pick that. You'd display a list generated from TimeZoneInfo.GetSystemTimeZones(), showing the DisplayName to the user, and using the Id for the value. The Id would be "Central Standard Time", which indeed is the correct identifier for US Central Time, inclusive of both CST and CDT - despite having the word "Standard" in the string.
You need to convert the TimeSpan to a DateTime, using the current Year, Month and Day. If you subtract from a TimeSpan without doing so, it can result in an unobtainable date.
Also, I noticed in your update that you left the results in a DateTime, so I did the same.
This code is showing you the time if the UTC time was 1:00 AM, as your problem states.
double offset = 5.00;
TimeSpan utcTime = new TimeSpan(1,0,0); //setting manually to your representation of 1 am.
DateTime newLocalDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, utcTime.Hours, utcTime.Minutes, utcTime.Seconds);
newLocalDateTime = newLocalDateTime.Subtract(TimeSpan.FromHours(offset));

Get UTC time for different timezone in mysql format

With dateObj.toISOString().slice(0, 19).replace('T', ' ') we can convert a date object to mysql datetime format in javascript. But the timezone is always considered as the client's (browser's) timezone.
I want to convert a date and time of different time-zones (not the browser's timezone) to UTC time and then to mysql time format.
Eg:
Alice is scheduling a meeting in New-York from Sydney. Alice enters New-York time as the input. Even thought the browser's location is Sydney, the javascript code has to assume the browser's location is in New-York and convert the date time to UTC, then to mysql format.
I can get current New-York time with, dateObj.toLocaleString('en-US', { timeZone: 'America/New_York'}). But not sure what to do next. Seems to be something to do considering time differences...
Anybody knows how to do this?
So you want to always store the date in the utc representation of where the event occurred.
To Save:
You know Alice has her Time Zone set to a specific value, therefore, you need to convert from Alice's time zone to UTC. If Alice entered 11:59:59 PM for the meeting time then the time stored would be when it occurred in GMT, which would be +4/5 hours depending on whether DST is being observed. It sounds like using your solution you would need a function like dateTimeUTC=FromSpecificTimeZoneToUTC(specificTimeZoneDateTime,'Eastern Standard Time')
dateObj.toLocaleString('en-US', { timeZone: '<TimeZone name for GMT>'})
To View:
Alice now has adjusted here Time Zone info to be in PST, which is GMT-8. Since we know the event occurred at 3:59:59 AM GMT we would need a function to convert from UTC back to a specific time, PST, this would yield 7:59:59 PM in Alices' changed config.
dateTimeSpecific=FromUTCToSpecificTimeZone(uTCTimeZoneDateTime,'Pacific Standard Time')
In my opionion you might be better served handling conversions like this on the server side where you have control over the tz info. I think a js might be too inconsistent because the time information is based on the client computers regional settings, not the preferred timezone of the operation. Plus, time zone info is subject to change. I don't know how js handles those changes.

Convert unix timestamp with a timezone to javascript date

I have a legacy web app that stores dates as a UNIX timestamp (seconds since the epoch 1970). Usually a timestamp like this represents UTC, however these timestamps are UTC-8. It doesn't look like it ever accounts for Daylight Savings Time (DST). I could convert it on the server to UTC and send to the client, but I would like to know if there is a javascript only solution.
Example Input:
1399335987
Example Output:
"2014-05-05T16:26:27-07:00" // Pacific Daylight Time (PDT)
The client should display the date/time according to their local machine. I looked into using momentjs but I could not find how to construct a date from a number without the number being UTC already. Is this possible?
Yes, it's possible given the unix timestamps are in UTC, with Moment Timezone (http://momentjs.com/timezone/)
moment
.unix(1399335987)
.tz('MST')
.format('YYYY-MM-DDTHH:mm:ssZ');
And you get
"2014-05-05T17:26:27-07:00"
Note here I'm using MST, and you should be able to use whatever timezone you want, via Timezone Data Builder (http://momentjs.com/timezone/data/)
Actually, by default, moment parses and displays in local time.
This means, only if you're in a different timezone (offset really) and still want to get the local time in MST, it's necessary to set the timezone as MST.
Otherwise, moment.unix(1399335987).format('YYYY-MM-DDTHH:mm:ssZ') is good to go.

What's the difference between datetime in ISO 8601 and UTC formats in javascript?

I pick some date and time in javascript and then want to store it on server (.NET). Dates are supposed to be in future from the current moment (so they won't be before 1970).
Having read topics here on SO I learnt it's better to store date as a string and people suggest using Date.prototype.toISOString() or Date.prototype.toUTCString().
I've read that toISOString() is not available in IE 7. And I'd like to know other differences, when I should choose one or another function.
They're for different purposes.
UTC is the primary time standard by which the world regulates clocks and time.
ISO is standard format time. ISO also supports ms in its format.
So if you want to send data to the server, send the ISO, because ISO is the standard format:
var date = new Date();
sendDate(date.toISOString());
You can also use toISOString in IE7 polyfill.
I hope it will helpful to you.
Summary About toISOString() :-
The toISOString() method returns a string in ISO format (ISO 8601 Extended Format), which can be described as follows: YYYY-MM-DDTHH:mm:ss.sssZ. The timezone is always UTC as denoted by the suffix "Z".
Refer Below link for more information about toISOString().
Date.prototype.toISOString()
Summary About toUTCString() :-
The toUTCString() method converts a date to a string, using the UTC time zone.
Refer Below link for more information about toUTCString()
Date.prototype.toUTCString()
Always use .toISOString()
They give almost the same information, but in different formats. Here is what I get on my machine.
new Date().toISOString()
"2019-10-11T18:56:08.984Z"
new Date().toUTCString()
"Fri, 11 Oct 2019 18:56:08 GMT"
There are 4 reasons .toISOString() is more often what you want than .toUTCString().
A. More convenient sorting
When you sort alphabetically, the "2019-10-11T18:56:08.984Z" pattern of .toISOString() gives you the correct date order.
B. Millisecond precision
.toISOString() provides millisecond values, whereas .toUTCString() does not.
C. Any user can interpret correctly
The .toUTCString() value may be more familiar to human end-users, but only if the language settings are suitable for them. In contrast, the .toISOString() is the same regardless of language settings.
D. Reproducibly regeneratable by software
You can easily convert the ISO date string to a Javascript Date object, and then back again, regenerating exactly the same string. This is regardless of who gave you the ISO date string, where the server is, and where you are.
This is not automatically true for the UTC string. For example, if a second instance of your app system is running in a different time zone, or language, it's .toUTCstring() may use different numbers or words (respectively) to represent the same instant in time. It will be difficult for it to create a UTCString that matches what was made by the first instance of the app, since in general it will not know the language or timezone in which the first UTC string was produced.
I think nobody needs .toUTCString()
I don't know why `.toUTCString()` exists. Its word-heavy format makes it useless for internal storage of dates in your program, because it varies depending on your language and timezone setting etc.
So maybe it is to produce something nice to display externally for the user to see? Well, not really. Anyone who is not in the London time zone will not find it very helpful.
I live in London. And even I, even if I was writing an app purely for use by me, solely on my system, and only in my home, would still not want to use .toUTCString(). Because it is showing UTC (also known as GMT). London is not always on GMT. In summer, we move to GMT+1, so the .toUTCString() result would mislead anyone who didn't notice the "GMT" and do the time adjustment in their head.
If I wanted a natural-language time, to make non-computer literate users comfortable, I would construct it manually from parts, using a library like moment.js. If I wanted a quick-and-dirty solution, I would use .toString() which at least will move to Summer time when appropriate.

Categories