time zones: user preference vs client-side Javascript - javascript

In Javascript it's fairly straightforward to render and manipulate dates in the current user's local time zone using the methods of the Date object. For example, toLocaleString() for output and the 7-argument form of the Date constructor for input. So up until now I haven't even bothered setting a time zone as a user preference. Internally everything is stored, computed and sent back and forth to the client using UTC, and we do the translation client-side for both input and output.
For example, suppose a user has their local machine's time zone set to US Eastern. When looking at my web page, an event that occurred at Unix timestamp 1359416775000 would render as, say "Mon Jan 28 18:46:15 2013" with code no more complex than
new Date(1359416775000).toLocaleString();
But suppose I need to send that user an email about this event. What time zone should I use to render the timestamp in this email? The obvious answer is to let the user pick their time zone. Now suppose I do this and this user picks US/Eastern. Great. Now suppose the next time the user logs into my website their local machine is on US Central time. That same piece of Javascript code would now cause the timestamp to render as "Mon Jan 28 17:46:15 2013".
Is this really the right behavior? The user has picked a time zone in my application, but it only applies to email?
This seems like a common enough problem that I feel like there ought to be a common best practice, I'm just wondering what that is.

You should, by default always display times in the users local time zone. At any point of you display the time using another time zone, this should be made clear by also printing the timezone.
As such, if the users time zone is US/Eastern, you would display a time in hos time zone, in your example "Mon Jan 28 18:46:15 2013", while if you show him an event that actually happens in US/Central, you should show "Mon Jan 28 17:46:15 2013 US/Central".
Now if the user moves to a computer whose time zone is US/Central, then yes, as default you should now show him the time in US/Central. So you would in both cases display the date as "Mon Jan 28 18:46:15 2013", no time zone necessary. They will have the computers current time in the corner of the screen, so it won't cause much confusion.
If you let the user pick his timezone, which is common in sites where the time display isn't decided by the client time zone setting, then you should by default show the times in that time zone all the time, no matter what time zone the computer is in. Remember that it is up to the user to make sure his computer is in the right time zone. Most people who travel with their laptops won't change the time zone when they move.
It is theoretically possible for you to warn the user that he has selected another time zone than the one he seems to be located in, by getting a geolocation from the IP. But unless you are writing a calendar application I would think that annoys people more than it helps them.

Unfortunately you cannot set the user's timezone which is used by the non-UTC date methods.
You can only work around that by adding/substracting your custom timezone offset when outputting/reading a date, like in this example.

Related

Future bookings maintain business timezone for displaying data when in other timezone

I am setting up a webapp for a business which takes future bookings which can also be recurring. At this moment, only the business can make the bookings.
Business rules:
The app must save a timezone against the user based on the business address provided at account registration. All events will be taking place at the business address. UPDATE: following comments, this rule will be changed to: Timezone will be recommended to the user user using a geocoding service (in the instance that a match is found), but user must confirm their timezone.
When logging in from another timezone, the webapp app booking system should still appear to the user to be set to the business timezone. (Potential scenario for this is the user is at a meeting abroad, but still wants to check up on their bookings). This should mean that they can still use the system as before eg. by adding new bookings. However, I believe this would mean the system has to ignore the user's local timezone, and apply the business timezone to any booking events.
I have the booking system working for a user that is within the same timezone. But when they change timezones the future bookings calendar breaks.
My app is nodeJS with postgresql. What I am confused about is what I should be persisting with regards to datetimes, and what relevant conversions to perform.
I think it would be prudent to save the client locale datetime always (even if not used as requirements may change), and also the UTC time. But I think I will have to also construct a date (in javascript) that takes the datetime selected and applies the business timezone to this (using eg. moment.tz.setDefault("America/New_York")?). I am unsure what to do about receiving this date on the client when viewing the scheduling information. How do I ensure that it displays with the business timezone?
You should always store the time zone that is relevant to the event. Since you said "All events will be taking place at the business address", then the time zone of the business is relevant.
If these are physical in-person events, then the user's current local time zone isn't relevant at all. For example, I would expect that if I made a dentist appointment in Los Angeles, that I would specify the time in Los Angeles even if I was making the appointment from New York.
However, if the events are virtual online events, then you may also want to add some logic in the UX to show both the time in the target time zone and the equivalent local time. For example, if I'm scheduling a video call next week with a person in Los Angeles, and I happen to be in New York today, you have no idea whether I will still be in New York at the time of the call or if I'll have travelled to Los Angeles by then. You should allow me to choose which time zone I'm creating the appointment in, and show both the time there and my equivalent local time.
The time zone itself should be stored as a varchar(14). IANA 2017c established a 14 character limit for individual segments of zone or link identifiers, removing the only link name that exceeded it, Canada/East-Saskatchewan. (If you have older data that includes that, replace it with America/Regina.)
For a single appointment, you should store the date and time of the appointment, in the time zone of the appointment. You should store this in a data type that holds the date and time without any time zone or offset. timestamp without time zone in postgres, datetime2 in MS Sql Server, etc.
You might think you should use a timestamp with timezone (or datetimeoffset type in SQL Server), but that would pin the appointment to the equivalent universal time, using the rules applicable at the time the appointment was scheduled. If those rules change before the appointment comes into effect, then the appointment will shift to a different local time. This is usually undesired. The point is to capture the intent of the user. In other words, if I say "8am on December 1st", then I mean that regardless of what my government does to my time zone between now and my appointment time.
You might also store the UTC time equivalent in a separate field, but you'd need to recompute it any time the server's time zone data was updated. (Such a field can be convenient to quickly query for upcoming events.)
For a recurring appointment, all the above still applies except that you'll need to store some form of recurrence rule. Some people like to store many fields for various components of the rule (such as one field for "daily", one field for "on Wednesdays", one field for the time of day, etc...). You can use the date and time types in your database if you like. Other people like to store a string with a chron expression. It really just depends on your needs.
It's especially important with recurring appointments to consider that the UTC equivalent for each occurrence will not necessarily be the same. Consider that many time zones alternate their UTC offsets based on whether daylight saving time is in effect. For example, if I'm creating a daily appointment in Los Angeles at 10 am, that would be 6 pm UTC during Pacific Standard Time, and 5 pm UTC during Pacific Daylight Time. Thus, you cannot just store the UTC time. Again, capturing the intent of the user is the most important part.

How do I get the result of javascript new Date().getTimezoneOffset() transferred to C# backend?

See the title: for the solution I'm working on, I need to get the current timezone offset (from the client, running javascript/jQuery) and use it in backend C# code.
The question is rather similar to the one asked here, but there are a few differences - the main one being that I am pretty sure that the time on the client computer won't be tampered with. So new Date().getTimezoneOffset() will do just fine.
I cannot read the value upon submitting a form since the user is not working in a form: after the user has logged in, among the items that are visible on the screen is a table with data entered by the user or by other users. This data contains UTC datetimes that have to be adjusted according to the client's timezone. C# code is responsible for retrieving and formatting the data - hence my question.
What would suffice, is storing the value somewhere so that C# can read it when necessary. But I don't think that can be done as well. What would be the approach here?
Thanks in advance!
Your suggested approach is flawed in that the current offset from the client's browser is only going to apply to the current date and time. In reality, time zone offsets change over time within a given time zone. You cannot just take a singular offset from one point in time and expect to use it to convert other dates and times to the same time zone. Instead, you need to use the string that identifies the time zone, not an offset from that zone.
As an example, consider the Eastern time zone in the United States. For part of the year, it uses UTC-5, and we call it Eastern Standard Time (EST). In another other part of the year, it uses UTC-4, and we call it Eastern Daylight Time (EDT). This time zone is identified by either the IANA time zone ID "America/New_York", or the Windows time zone ID "Eastern Standard Time" (which covers the entire zone, both EST and EDT despite its wording).
So, break this problem apart into a few steps:
In JavaScript, identify the users's IANA time zone (America/New_York):
If you are targeting modern web browsers, you can call this function:
Intl.DateTimeFormat().resolvedOptions().timeZone
If you need to support older web browsers, you can use jsTimeZoneDetect, or moment.tz.guess() from Moment-Timezone.
Send that string to your web server through whatever mechinsm you like (form post, XHR, fetch, etc.)
In your .NET code, receive that string and use it to reference the time zone and do the conversion. You have two options:
You can use Noda Time, passing the IANA time zone ID to DateTimeZoneProviders.Tzdb as shown in the example on the home page.
You can use .NET's built-in TimeZoneInfo object. If you're running .NET Core on non-Windows systems (Linux, OSX, etc.) you can just pass the IANA time zone ID to TimeZoneInfo.FindSystemTimeZoneById. If you are on Windows, you'll need to first convert it to a Windows time zone ID ("Eastern Standard Time"). You can use TZConvert.GetTimeZoneInfo from my TimeZoneConverter library.
Once you have either a DateTimeZone from Noda Time, or a TimeZoneInfo object, you can use the methods on it to convert UTC values to local time values for that time zone. Each of these will apply the correct offset for the point in time being converted.
I'll also say, many applications simply ask the user to choose their time zone from a dropdown list and save it in a user profile. As long as you're storing a time zone identifier string and not just a numeric offset, this approach is perfectly acceptable to replace steps 1 and 2 above.

Moment.js uses a different time zone than the one defined in the system

I'm running Moment on a laptop with Windows 10 in EST, timezone UTC-05:00. I didn't define the daylight savings time in the laptop, but when I run the code below Moment converts the date to UTC-04:00. Why does Moment use a different timezone than the one defined in the laptop?
var ts = "2019-04-01T18:22:57.813";
var dateTime = moment(ts, 'YYYY-MM-DD HH:mm').toDate();
console.log(dateTime);
... Windows 10 in EST, timezone UTC-05:00. I didn't define the daylight savings time in the laptop...
From your explanation, I assume your time zone settings look like this:
The (UTC-05:00) Eastern Time (US & Canada) display name matches the Windows time zone ID of Eastern Standard Time, which corresponds to the IANA time zone ID of America/New_York. That time zone currently uses UTC-5 during standard time and UTC-4 during daylight time. It doesn't matter that it says "(UTC-05:00)" in the display name string, it still honors DST as applicable in that time zone.
The "Adjust for daylight saving time automatically" feature is normally turned on for time zones that have daylight saving time. Turning it off, as shown here, is generally not recommended. The problem is that some software will not evaluate that flag, and simply look at the time zone identifier. For web browsers, you'll find that Edge will honor this flag, but Chrome will not.
There's really no good reason to disable this. If you need a time zone that is UTC-5 without DST, such as (UTC-05:00) Bogota, Lima, Quito, Rio Branco, then simply choose that time zone.
And lastly, recognize that this has nothing to do with Moment.js. You will see the same behavior just with the JavaScript Date object. Since DST is in effect in US Eastern Time on April 1st, then you will see UTC-4 for that date.
On the other hand, if what you really wanted was to interpret the given date and time as being in UTC-5 regardless of the local computer settings, Moment can help you with that:
var m = moment.parseZone("2019-04-01T18:22:57.813-05:00");
m.format() //=> "2019-04-01T18:22:57-05:00"
Though if you do m.toDate(), then you'll get back a Date object, which is once again going to pick up the computer's local time zone. For this scenario, try to avoid Date objects if you can.
By default moment.js use local time zone (node timezone): https://momentjscom.readthedocs.io/en/latest/moment-timezone/01-using-timezones/05-default-timezone/
And if unset, by default node.js use UTC timezone, check out:
Where does Node.js get it's timezone and how can I set it globally?

How to maintain Timezone

My client is in india and server in USA . If user submit his post from india it get stored in USA server so when i display post submit time to user it is as per USA time . I want to show it as per clients timezone
The simplest way to handle timezones is to work with Epoch time behind the scenes, and translate it to the user's preferred timezone on render (or with client-side code).
Epoch time is the number of seconds since it became 1 January 1970 in London. For example, right now the time is 1483130714. This means we've got one simple number, that can be effortlessly compared and sorted, to represent precise moments without needing to care about dates, timezones, locales and their frustrating details. Virtually all languages in popular use have the ability to parse these numbers into their own timestamp values. In JavaScript, you can do this with new Date(1483130714). You'll get a date object and you can then present that however you like (eg with toLocaleString).
If you don't use Epoch time, you'd want to use UTC, the next-best thing. The important thing is to store in a consistent universally-understood format and then translate it to the user's preferred form as needed.
You need to store date in UTC and then convert it as per browser culture and timezone. So store all dates in UTC and depending on browser culture you can add offset, this could be tricky if user sets wrong culture and time.

A Javascript based time picker control which converts the selected time into utc

I am looking for a JavaScript based time picker (jquery, extjs, bootstrap etc) control which converts the local time into UTC time. It must take into consideration user location and provide accurate time.
There are lot of controls available which allows you to pick time but I want to know what is the most accurate way to convert the time into UTC equivalent. There are lots of post available which talks about converting time into UTC but some of the post are old and some of them have one or the other catch.
What I am trying to do:
Assume the local time on user machine is 10 AM. I am asking user to pick a time > current time (or a future time). Assume user picks 11:30 AM. I want convert the 11:30 AM (local to his timezone) into UTC equivalent.

Categories

Resources