Moment Timezone: UTC offset difference - javascript

I use the moment-timezone v.0.5.3-2016c library to calculate the UTC offset for a timezone:
var z = moment().tz("America/Los_Angeles");
z.utcOffset(); // -420 mins or -7 hours
// check if DST is shifted
z.isDSTShifted(); // false
But here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones the UTC offset for the America/Los_Angeles is -8 hours.
Moment uses the tzdb v.2016c and the wikipedia article too.
Well, why there are two different results here? And which result is right?
P.S.: there is the same difference for America/Kentucky/Monticello and Europe/Tiraspol, as well.

Calling the moment creation function, moment() without any arguments returns the current moment in time. Since time zone offsets vary depending on what date and time they are attached to, your results will vary depending on when you call this function.
If you want to know whether or not the time is daylight saving time or not, use isDST. The isDSTShifted function is for dealing with invalid local times, not checking DST. It probably could have been named better.

The USA is currently in DST (Daylight Savings Time). Therefore, I'd use the UTC DST Offset column, which shows -07:00.

Related

Date difference changing based on timezone

I have a server date time which is also CST and a date based of chicago timezone, when i find the difference between two dates the value is different for different timezones.
I am not able to get to the problem.
Date A is my Chicago time 2019-05-22T04:02:14-05:00
Date B is my server time 2019-05-20T01:39:34-04:00
Hours difference between them 51 when my timezone is set to EST
When i change my timezone to IST
Date A is my Chicago time 2019-05-22T04:03:34-05:00
Date B is my server time 2019-05-20T01:39:34+05:30
Hours difference between them 60 when my timezone is set to IST
Why is there a difference in hours when the dates are same in both the cases?
getIntervalTime(dateA, dateB): ITimer {
console.log("Date A is my Chicago time", dateA)
console.log("Date B is my server time", dateB)
console.log(moment.utc(dateA).diff(moment.utc(dateB), "hours"));
intervalHours = moment.utc(dateA).diff(moment.utc(dateB), "hours")
}
In your question, you gave two very different server times. They are not referencing the same actual point in time. In each case, 01:39:34 is the local time in the time zone offset provided.
2019-05-20T01:39:34-04:00 (EDT) = 2019-05-20T05:39:34Z (UTC) = 2019-05-20T11:09:34+05:30 (IST)
2019-05-20T01:39:34+05:30 (IST) = 2019-04-19T20:09:34Z (UTC) = 2019-04-19T16:09:34-04:00 (EDT)
As you can see just by comparing the UTC times, there is a 9.5 hour difference between these two timestamps. This is also reflected in the difference between the two offsets (5.5 - -4 = 9.5).
This is a common source of confusion, as often people view the + or - sign as an operator, and thus think of it as an instruction ("Oh, I see a plus or minus so I must need to add or subtract this value to get to the local time"). But in reality it is not an operator, but the sign of the offset. Positive offset values are ahead of UTC, while negative offset values are behind UTC. (Alternatively one can think of positive offsets as being east of GMT, while negative offsets are west of GMT.)
In other words, the date and time portion of an ISO 8601 formatted timestamp are already converted to the context provided.
Also note that the time zone of your server won't really matter, nor should it. Now is now - time zones don't change that. Thus, in most cases you should simply use the UTC time.

Want to get Timezone using jquery

In jquery,
var date = new Date();
It is taking system Date Not site Time zone
var date = (new Date()).getTimezoneOffset();
it is also not working.please anyone help for this.thank you.
Return the timezone difference between UTC and Local Time:
var d = new Date()
var n = d.getTimezoneOffset();
The result n will be:
-300
The getTimezoneOffset() method returns the time difference between UTC time and local time, in minutes.
For example, If your time zone is GMT+2, -120 will be returned.
Note: The returned value is not a constant, because of the practice of using Daylight Saving Time.
Tip: The Universal Coordinated Time (UTC) is the time set by the World Time Standard.
Note: UTC time is the same as GMT time.
jQuery has only one date/time function, which is $.now()
If you meant JavaScript, the answer is still no. You can only obtain a time zone offset from date.getTimezoneOffset(). You can't get a time zone - at least not in all browsers.
You can guess at the time zone, by using the jsTimeZoneDetect library, but it is just a guess. It may or may not be accurate.
If you can guarantee your users are running a browser that supports the brand new ECMAScript Internationalization API, you can get the user's time zone with:
Intl.DateTimeFormat().resolvedOptions().timeZone

Extracting utcOffset from an ISO String with Moment.js

Using moment.js, I'm attempting to extract the offset from an ISO date string so I can use the offset later when formatting an epoch timestamp to ensure the conversion of the timestamp is in the same timezone.
Even though the offset in the string is -0400, the result is always 0;
var currentTime = "2015-03-18T16:10:00.001-0400";
var utcOffset = moment(currentTime).utcOffset(); // 0
I've attempted to use parseZone() as well without success. Is there a way to extract -0400 from the string so I can use it while formatting another time?
Thanks for the help!
KC
The correct way to extract the offset is indeed with parseZone
var currentTime = "2015-03-18T16:10:00.001-0400";
var utcOffset = moment.parseZone(currentTime).utcOffset();
This should result in -240, which means 240 minutes behind UTC, which is the same as the -0400 in the input string. If you wanted the string form, instead of utcOffset() you could use .format('Z') for "-04:00" or .format('ZZ') for "-0400".
The form you gave in the question just uses the computer's local time zone. So it is currently UTC+00:00 in your time zone (or wherever the code is running), that would explain why you would get a zero. You have to use parseZone to retain the offset of the input string.
Also - your use case is a bit worrying. Remember, an offset is not the same thing as a time zone. A time zone can change its offset at different points in time. Many time zones do this to accommodate daylight saving time. If you pick an offset off of one timestamp and apply it to another, you don't have any guarantees that the offset is correct for the new timestamp.
As an example, consider the US Eastern time zone, which just changed from UTC-05:00 to UTC-04:00 when daylight saving time took effect on March 8th, 2015. If you took a value like the one you provided, and applied it to a date of March 1st, you would be placing it into the Atlantic time zone instead of the Eastern time zone.

Date ranges with DST in javascript

I'm looking for best practices regarding dates - where it's the date itself that's important rather than a particular time on that day.
An excellent start was this question:
Daylight saving time and time zone best practices
I'd like some guidance applying this for my situation. I have medications starting on a particular date, and ending on another. I then need to query medications which are active in a given date range.
I've tried setting start and end dates as midnight local time, then storing in UTC on the database. I could add timezone entries too.
I'm using moment.js on both client and server, and can use moment timezone if needed.
I'm wondering how to deal with the effect of DST on my times - which makes an hour difference in my locally-midnight UTC times between DST and non DST periods.
The problem I have is for example when some medications have end dates set during a DST period, and some which were set in a non-DST period. Then, their UTC times differ by an hour. When a query is made for a particular date range starting at local midnight, it's not accurate as there are two different representations of midnight. The query itself may treat midnight as one of two different times, depending on when in the year the query is made.
The end result is that a medication may appear to end a day later than it should, or start a day earlier.
A simple but wonky workaround would be to consistently set the start date as 1am in standard (non DST) time, and end dates as 11:59pm standard (non DST) time, and query at midnight.
Or, should I check the start and end dates of each query, and work out what the UTC offset would be for each date?
But I'd much prefer to know what best practice is in this situation. Thanks.
Both the JavaScript Date object and the moment object in moment.js are for representing a specific instant in time. In other words, a date and a time. They internally track time by counting the number of milliseconds that have elapsed since the Unix Epoch (Midnight, Jan 1st 1970 UTC) - ignoring leap seconds.
That means, fundamentally, they are not the best way to work with whole calendar dates. When you have only a date, and you use a date+time value to track it, then you are arbitrarily assigning a time of day to represent the entire day. Usually, this is midnight - but as you pointed out, that leads to problems with daylight saving time.
Consider that in some parts of the world (such as Brazil) the transition occurs right at midnight - that is, in the spring, the clocks jump from 11:59:59 to 01:00:00. If you specify midnight on that date, the browser will either jump forward or jump backward (depending on which browser you are using)!
And if you convert a local date-at-midnight to a different time zone (such as UTC), you could change the date itself! If you must use a date+time to store a date-only value, use noon instead of midnight. This will mitigate most (but not all) of the adjustment issues.
The better idea is to treat whole dates as whole dates. Don't assign them a time, and don't try to adjust them to UTC. Don't use a Date or a moment. Instead, store them either as an ISO-8601 formatted string like "2014-11-25", or if you need to do math on them, consider storing them as an integer number of whole days since some starting value. For example, using the same Jan 1st 1970 epoch date, we can represent November 11th 2014 as 16399 with the following JavaScript:
function dateToValue(year, month, day) {
return Date.UTC(year, month-1, day) / 86400000;
}
function valueToDate(value) {
var d = new Date(86400000 * value);
return { year : d.getUTCFullYear(),
month : d.getUTCMonth() + 1,
day : d.getUTCDate()
};
}
There are a few other things to keep in mind when working with whole dates:
When working with ranges of whole dates, humans tend to use fully-inclusive intervals. For example, Jan 1st to Jan 2nd would be two days. This is different from date+time (and time-only) ranges, in which humans tend to use half-open intervals. For example, 1:00 to 2:00 would be one hour.
Due to time zones, everyone's concept of "today" is different around the globe. We usually define "today" by our own local time zone. So normally:
var d = new Date();
var today = { year : d.getFullYear(),
month : d.getMonth() + 1,
day : d.getDate()
};
You usually don't want to shift this to UTC or another time zone, unless your business operates globally under that time zone. This is rare, but it does occur. (Example, StackOverflow uses UTC days for its calculations of badges and other achievements.)
I hope this gets you started. You asked a fairly broad question, so I tried to answer in way that would address the primary concerns. If you have something more specific, please update your question and I'll try to respond.
If you would like even more information on this subject, I encourage you to watch my Pluralsight course, Date and Time Fundamentals.

Set JavaScript countdown to end at midnight PST?

I am trying to get a countdown to end Monday # midnight PST. I thought I had it working a week ago but apparently not.
I am using date.js
var monday = Date.today().next().monday();
var UTCmonday = new Date(monday.getTime() + monday.getTimezoneOffset() * 60000);
var PSTmonday = new Date(UTCmonday.setHours(UTCmonday.getHours() + 9));
$('#defaultCountdown').countdown({until: UTCmonday});
I think the problem is in determining UTC time? Am I right? How do I work this out?
Assuming you Pacific Standard Time, then you need to remember that PST === UTC-8
Thus, your third line would be
var PSTmonday = new Date(UTCmonday.setHours(UTCmonday.getHours() - 8));
The problem with this is that this will fail if the UTC is any earlier than 8am, since you can't pass a negative number into setHours.
Since you're using Datejs, why not use its full capabilities for changing the timezone?
http://code.google.com/p/datejs/wiki/APIDocumentation#setTimezone
Getting the time strictly in PST doesn't make much sense, as for almost half of the year PST isn't observed in the Pacific time zone. PST (UTC-8) is observed in the winter, and PDT (UTC-7) is observed in the summer. You can't represent Pacific Time as just a fixed offset, and unless it happens to be your own local time zone, you can't easily determine the transition between them without a time zone database. See the timezone tag wiki.
Also, date.js has been abandoned. I can't recommend any solution that continues its use. Support for the setTimezone method that Dancrumb suggested is culture specific, and it still doesn't take daylight saving time into consideration.
Instead, I recommend trying moment.js. You can use the moment-timezone add-on to work with the America/Los_Angeles zone - which is a good exemplar of US Pacific time. Make sure your moment-timezone-data.js file includes at least this zone. Then you can do the following:
var m = moment().tz('America/Los_Angeles').day(7).startOf('day');
var s = m.toISOString(); // if you need a string output representing UTC
var dt = m.toDate(); // if you need an actual JavaScript Date object
Let's break that down a bit:
moment() gets you the current time
tz('America/Los_Angeles') adjusts the time to the timezone you are interested in.
day(7) advances the time to the next Monday.
startOf('day') snaps the time back to midnight.

Categories

Resources