I am building a small web application that has some time based aspects to it like displaying and hiding things based on what hour in the day it is. My friend told me that this will work until DST comes around and then I will have to change all of the hour checks I have in place. Is this true?
When creating a new Date() it will represent the user's current time regardless of circumstances. From MDN:
When no parameters are provided, the newly-created Date object represents the current date and time, specified in the local time zone, as of the time of instantiation.
I would strongly recommend not trying to handle DST yourself, because it becomes heinously complicated once you get into the weeds.
Related
How can I modify a raw Unix timestamp so that it shows that it is 5 hours behind (as an example). I'm looking to do this with a javascript or python. The more lightweight the better. I'm basically looking for how to manually decode a given unix timestamp and change some of its numbers so that it gives me back a unix timestamp showing a different time. It would be even greater if I could automatically adjust it to a users personal time-zone using javascript/python.
Convert to the number of hours you want to offset by to seconds, and then add or subtract it from the Unix timestamp. As far as getting the user's personal time zone, I'm not sure how you would do that without language specific code.
How to choose a time 5 hours numerically smaller
This would be relevant for if, for example, you were testing whether the submission of an exam answer is within 5 hours of the exam's start time.
For this, just subtract 5 * 3600 * 1000 from the Unix timestamp's numerical value.
What you are actually proposing to do is extremely unwise
You seem to be planning to create a Unix timestamp of a different point in time which, when expressed as UTC but with the annotation "UTC" deleted, will match the local time display expected by a user who is 5 hours behind UTC. I can see why you are tempted to do this but it is a very bad idea.
Unix Timestamps do not default to be in UTC, they describe a point in time across all of space simultaneously. If you shift the value of a Unix timestamp, it is no longer a Unix timestamp, just as (mass of car minus 50 kg) is no longer the mass of that car. The value is either the mass of a different car that is 50kg lighter, or an incorrect value for the mass of the original car.
Unix timestamps are unambiguous. Once you know that a variable contains a Unix timestamp, you can stop worrying about any if's, but's or maybe's. It is solid and definite. What you are creating is a horrible thing which looks like a Unix timestamp of an timepoint, but it is not. What variable name are you going to give it to prevent confusion? You might give the physical property a new name, such as the goalieTimeStamp, which is distinguished from Unix timestamps by being displaced by 5 hours.
If a person is 5 hours behind UTC now (in January), that person will likely be a different number of hours behind UTC in summertime. This is a mess.
I think you are doing this so that you can display a local time nicely. Choose a different, better, way to achieve this.
You should use the localisation system in the relevant language to obtain and display the local time, which will depend not only on the location of the user, but also the time of year. This will also allow you to deal with languages etc, if you need to.
And throughout your code you will have a clear distinction between the timepoint of your event (invariant across space) and how a local user will express that time in their timezone, time of year and language.
A good library for this in Javascript is moment.js. It is rather heavyweight, but this is because the task is much more heavyweight that it first seems!
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.
I'm trying a very simple idea but hard to implement one.
I want to return the difference between two given dates and times in seconds. Note I want to get the same result in these conditions:
No matter if we test it in Chrome or Firefox. it should return the same result in both.
No matter if the end-user sets the Time Zone in his/her system in different time zones.
So I tried this:
// input your custom Date below
const date = new Date('2020-6-24 14:22:00'); // Set End Time
const dif = (date.getTime() / 1000) - ((new Date().getTime())/1000);
console.log(dif);
if you check this with different browsers with different timezones set in your system you will get different results!
I want all users (Those who set the timezone to Havana and Those who set the time zone to Tehran on their systems) see the same result.
The same result is the only thing I can think of right now.
The wired and confusing thing here is that if I log this simple log, I have different results in Firefox and Chrome:
console.log(new Date());
Note: I set my system's timezone to Havana.
There can definitely be many issues with handling dates and times, including time zones, leap years, leap seconds, and daylight savings time.
However that doesn't seem to be what's happening here. Remember that internally JavaScript Date objects use universal time (UTC), so once you have the time stored correctly, comparisons should work regardless of the time zones.
I used this function:
const dateDiffSeconds = function(date1, date2) {
return Math.round(Math.abs(date1.getTime()-date2.getTime())/1000);
}
Note that I'm using Math.round() to round up as well as Math.abs so it doesn't matter which date is larger. Notably, you can even subtract dates directly without getTime().
When I ran it in Firefox, Chrome and Node using various tests I got consistent results, including when I changed time zones.
One test to run is this: instead of using the current time, compare two preselected constant dates.
I suspect you're having trouble with one or both of these things:
Time zone representation: Specify the date in UTC time. If you want a user in Tehran to see the same time difference as in Havana, you have to make sure you send them both the same date. If the date is sent without the time zone specified, both clients will convert the date into local time, which means they'll be separated by time zones. Instead, send the dates in UTC time.
Browser synchronization: It's possible also that when you're testing the results in two different browsers, you're not keeping them synchronized tightly enough. When I tested it, I used setInterval() with a low timeout setting (much lower than a second) to keep comparing the current time with the test date. If you're just refreshing the browsers manually the times likely won't be the same.
It's probably easier to use Date.now() instead of new Date(). This returns a number of milliseconds that you can easily subtract.
Just don't forget that time measurement on computers is weird. You can end up with end - start < 0 for a variety of reasons.
Let's say I have a user of my application set a recurring event. His timezone is America/Denver, so I store that along with an rrule that determines when the recurrences happen.
This works assuming that both my server and all of my users are in the same time zone. However, let's say I have other users, in America/Pheonix and maybe America/New_York who wants to get the occurances of this event the user has defined. I need to be able to create the events using the America/Denver time, but then return them to the user in UTC. Conversely, I also need to calculate recurring events that users in America/New_York defined and return those as UTC to the user.
Is there a library that exists that I can give it a timezone and an rrule and have it generate the recurring events based on that timezone's rules (like respecting DST)? Or maybe a third party API?
EDIT: Here is some clarity to my problem.
Let's say I have a recurring event that occurs every Friday at 9am. If I set this event in Colorado, the times that this event occurs are going to be slightly different than times in Arizona, which doesn't have DST for the 5 months of the year that Colorado does. So in my database, I need to store the time zone, and I need some way to generate the events based on that time zone's rules. This is the part I am stuck on, finding a way to generate the events based on the time zone's rules.
I need some way to generate the events based on that time zone's rules
No, you don't. The "time zone's rules" are irrelevant to the generation of occurrences. An event at "every Friday at 9am" is going to be at 9am all year round, whether DST is active or not. In other words, you can (and should) completely ignore DST for the rrule part.
The only thing you need to do is keep the original time zone along with each occurrence - a date and a time is not enough - then simply convert the date/time to another time zone on the fly, when you need to display it to a different user.
I have used Moment.js and Moment Timezone to work with dates before, but you probably have other options out there.
I'm using moment and moment-timezone in javascript, and this part of it is one of the most unintuitive API's I've ever seen.
I would expect that:
moment("2015-12-14T04:00:00Z").utcOffset()
would be a pure function and return the offset included in the argument, which is 0. But instead it implicitly converts it to my local timezone offset (PST), so this returns -480 Why?? I asked what offset the object i just created has, not what offset I'm currently in. It would be like if I wrote an api where calling User.find(123).name() returns your name instead of the name of user 123.
Anyway, I can do
moment("2015-12-14T04:00:00Z").tz("utc").utcOffset()
But my datetime string is dynamic, so I don't know the timezone.
How can I get the behavior I expected, a Moment in js that is in the timezone offset included in the string i passed in?
Use parseZone to keep the offset as it was passed in.
moment.parseZone("2015-12-14T04:00:00Z")
As to the "why?" part of your question:
moment(...) is local mode. Ambiguous input (without offset) is assumed to be local time. Unambiguous input (with offset) is adjusted to local time.
moment.utc(...) is utc mode. Ambiguous input is assumed to be UTC. Unambiguous input is adjusted to UTC.
moment.parseZone() keep the input zone passed in. If the input is ambiguous, it is the same as local mode.
moment.tz(...) with the moment-timezone plugin can parse input in a specific time zone.
Keep in mind that moment has to contend with a wide variety of inputs.
Also keep in mind that a time zone and a time zone offset are two different things. An offset of -08:00 doesn't necessarily mean you are in the US Pacific time zone.