I want Client timezone name (e.g. India Standard Time) in ASP.Net MVC Application.
So, I Can use TimeZoneInfo.FindSystemTimeZoneById(TimeZoneName) function.
I have tried with new Date().getTimezoneOffset() (reference)
But, there is problem with Daylight Saving Time in this Code.
In javascript, i have also tried with new Date().toString()
But, this gives result in different format with different browser.
In firefox, chrome & safari,
Answer is "Tue May 08 2012 14:00:00 GMT+0530 (India Standard Time)"
In IE8, it is "Tue May 8 14:00:00 UTC+0530 2012"
Similar problem with opera also.
So, this method will not work for IE & Opera.
What will be best way to identify Client TimeZone?
the best and the most utilized way is to identify clients location thru some 3rd party library and database utilizing the ip of the client.. and then based upon the location of the client decide the timezone
Do you need to know the timezone or just the offset from UTC? Because timezones are not an ISO standard and can be changed almost arbitrarily, I prefer to work with the client's offset from UTC and I always get it from the client at login time or whenever they submit a form on which I need the client time. Sometimes I work out the GTM offset of the client and persist it to use wherever I display or use a time.
So I have a global JavaScript function like this which returns the given local date as a universal string:
function aspClientDateTime(dateObject) {
return dateObject.getFullYear() + '-'
+ this.leadingZero((dateObject.getMonth() + 1), 2) + '-'
+ this.leadingZero(dateObject.getDate(), 2) + ' '
+ this.leadingZero(dateObject.getHours(), 2) + ':'
+ this.leadingZero(dateObject.getMinutes(), 2) + ':'
+ this.leadingZero(dateObject.getSeconds(), 2);
}
On form submit, I get the current client date and store it in the form:
myForm.clientTime.val(aspClientDateTime(new Date()));
You then know what time it is in the browser and you can work out UTC offsets etc on the server.
The problem with timezones is that any government could introduce a new one tomorrow, as Samoa recently did. Typically I want to know what the offset of the user is right now, not what timezone they are in.
If it is the latter you really need, you might have to ask them, in the same way that Skype does it.
There is a library for detecting the timezone through JavaScript. It'll give you the name of a good enough timezone. It does not do geolocation or ip-lookup so it is very fast, but it is not extremely exact. For example it'll return "Europe/Berlin" for anyone in the Central European Timezone. It should be good enough for server side datetime normalizations however.
https://bitbucket.org/pellepim/jstimezonedetect
Related
I want to send design an API and send a Javascript Date() Object (including Time ) to a PHP Backend.
I have a solution with timestamp now:
//Javascript
new Date().getTime()
which return a number like: 1525094344392
and I send to my PHP Backend which converts it to a PHP Datetime Object:
<?php
$date = new DateTime();
$date->setTimestamp(1525094344392 / 1000);
This works, but there is no timezone set, so I am wondering if there is a better solution. I have not found a simple format in Javascript which both, PHP and Javascript, easily understand.
Please provide a code sample.
If you are sending this data across the world so that people can view it in different countries, if the code turns it back into date format, it will also set it to their browsers location....https://www.w3schools.com/js/js_date_formats.asp talks about this.
When setting a date, without specifying the time zone, JavaScript will
use the browser's time zone.
When getting a date, without specifying the time zone, the result is
converted to the browser's time zone.
In other words: If a date/time is created in GMT (Greenwich Mean
Time), the date/time will be converted to CDT (Central US Daylight
Time) if a user browses from central US.
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));
I am receiving a MySQL Timestamp in UTC and trying to covert it to the client's local timezone. However, When i do this I get the wrong time zone.
Ive formatted my DateTime String to be: var utcTime = 2014-05-15T13:00:00Z
However when after my conversion my dateObject is: Date {Thu May 15 2014 09:00:00 GMT-0400 (EDT)}. However, I want my Timezone to be GMT -0500 (EST).
I've searched online and saw there is a way to do this by appending "UTC" to a MYSQL formatted Timestamp.. However, this method does not work in all browsers.
If anyone has any insight on converting timezones i would appreciate it.
The D in EDT stands for Daylight and the S in EST stands for Standard. EDT should be used during Summer in the U.S. and EST in the Winter (list of countries here). Is it possible that GMT -4 (EDT) is actually the right local time? If it would be more towards winter it would switch automatically to GMT -5 (EST). The client timezone together with daylight savings is handled automatically by Javascript.
For example, the default string representation of a certain date in Javascript should correctly choose between Standard time and Daylight Savings time based on the date object itself and the machine timezone:
var date = new Date(millisSinceUnixEpoch);
alert(date.toDateString() + ' ' + date.toTimeString());
Note: there's room for a lot of assumption though. E.g. not sure exactly how your 'conversion to local timezone' code looks like
I've seen something similar to this. This MSDN article may explain it.
Handling daylight saving time using JavaScript
http://msdn.microsoft.com/en-us/library/ie/jj863688%28v=vs.85%29.aspx
In Windows Internet Explorer 9 and previous versions of Windows
Internet Explorer, dates are customized by applying the ECMAScript
specification's rules for storing daylight saving time adjusted times
internally. To improve accuracy, especially with dates in the past
(historical dates), Internet Explorer 10 relies on the system's rules
for storing daylight saving time adjusted times. This topic contains
the following sections:
var d = new Date();
// returns correct value "Fri Sep 26 2014 01:16:31 GMT+0300 (E. Europe Daylight Time)"
d.toString();
// returns incorrect value one hour behind "9/26/2014 12:16:31 AM"
d.toLocaleString();
It seems toLocaleString() is not taking DST into account for this test case.
How are local times calculated by Date (eg, does Chrome apply DST rules itself or via OS) and how/why does the algorithm differ between toString() and toLocaleString()?
Is this a bug or intended behavior?
Tested on Chrome/37.0.2062.120 with location Nicosia, Cyprus (http://www.timeanddate.com/time/zone/cyprus/nicosia)
On a hunch, I tried changing my Windows time zone to:
TZ Key / ID: "E. Europe Standard Time"
Display name: "(UTC+02:00) E. Europe"
After restarting Chrome, I was then able to get the same thing you showed:
Taking a closer look, at the localization properties:
So it would seem that there is no time zone understood by Chrome. This is because Chrome uses ICU, which uses the CLDR mappings for Windows time zones. That particular time zone is now considered "unmappable" - as there is no IANA time zone identifier that matches this Windows zone.
Note that this zone used to be mapped to Asia/Nicosia, but it was changed in the last revision of CLDR, as described in CLDR #6973
The reason for the discrepancy is that the toLocaleString function uses the ECMAScript Internationalization API, while toString does not. The prior is dependent on ICU and CLDR, while the latter just asks the OS for a time zone string.
The fix is for the user to switch their time zone to the correct setting. For Cyprus, it should be:
TZ Key / ID: "GTB Standard Time"
Display name: "(UTC+02:00) Athens, Bucharest"
When looking at the options in the Windows Time Zone Control Panel:
Be sure to close all Chrome windows completely after making the time zone change, as Chrome will not properly initialize time zones until it is restarted.
Now, the issue I mentioned earlier in comments is still a problem, as Intl.DateTimeFormat().resolvedOptions().timeZone now returns Europe/Kiev, and it should return either Asia/Nicosia, or Europe/Bucharest. But it is good enough to return the correct value for toLocaleString - at least most of the time.
I thought about letting my users having to select their own timezone in my application, but what about instead making it automatic with some javascript?
Some psuedocode:
A date is printed serverside as <p class="utcDate">2011-09-28 11:00 UTC</p>. When the user loads the page, jquery walks through all elements with the utcDate class and replaces the UTC date/time with a date where the diff between UTC & the users local timezone has been applied.
What should I be aware of when doing this? Are there any obvious drawbacks to this?
Thanks
If you do this (which there is nothing wrong with) be aware that it can affect perceived page-load time if there is a lot of elements involved.
Be sure to do the replacement in a DOM-ready event handler and not on page load, since this would be very visible to the users.
Alternativly instead of outputting the UTC date and then changing it, why not just output a js.snippet that will write the correct date inline via document.write? - This will be faster for pageload.
If it's the same date/time everywhere you use it on a page, you can just generate it once via js, and then simply output the value stored in a variable.
I'd recommend outputting the Unix timestamp instead. The js Date object doesn't have the capabilities to consume a UTC string directly (you'd have to parse out each component), but it can consume a timestamp using the setTime function.
The Date object automatically localizes to the user's settings and can be cast to a string directly (although that's probably more verbose than you'd like: "Wed Sep 28 2011 07:03:26 GMT-0400 (Eastern Daylight Time)"), so you'll likely want to format the string yourself:
$('p.utcDate').each(function () {
var time = new Date();
time.setTime(this.innerHTML);
this.innerHTML = time.toDateString();
});
As an added benefit, toDateString will handle local conventions around m-d-y vs d-m-y, etc.