Google Time Zone API incorrect number of hours? - javascript

I'm trying to compare the hours in between a website visitors location and a set location, by grabbing their current time, and then inserting that in to the Google Time Zone API with the location. However, no matter how I twist and turn it, it's either 1 or 2 hours incorrect, it seems.
Am I reading something wrong?
The request:
https://maps.googleapis.com/maps/api/timezone/json?location=40.7127753,-74.0059728&timestamp=1569956387&key=API_KEY
The Output:
{
"dstOffset" : 3600,
"rawOffset" : -18000,
"status" : "OK",
"timeZoneId" : "America/New_York",
"timeZoneName" : "Eastern Daylight Time"
}
The first part of the request is the longitude and latitude of New York City (retrieved from Google Places API), and the second value (timestamp) is seconds since 1 January 1970. This I get from the visitor with the following JavaScript:
+ new Date()
if (!Date.now) {
Date.now = function() { return new Date().getTime(); }
}
Math.floor(Date.now() / 1000)
..which for me results in: 1569956387 (seconds)
Date.now() returns milliseconds since 1 January 1970, so I need to convert to seconds by dividing by 1000 as Google Time Zone API uses seconds since 1 January 1970.
And according to Google Time Zone API docs:
rawOffset: the offset from UTC (in seconds) for the given location. This does not take into effect daylight savings.
..rawOffset is the JSON output
timestamp specifies the desired time as seconds since midnight, January 1, 1970 UTC. The Time Zone API uses the timestamp to determine whether or not Daylight Savings should be applied, based on the time zone of the location. Note that the API does not take historical time zones into account. That is, if you specify a past timestamp, the API does not take into account the possibility that the location was previously in a different time zone.
..timestamp is the seconds since 1 January 1970 specified in the request link
My local time is currently 9:59 PM (1569956387). Calculating either (18000/60)/60 or (21600/60)/60 tells me New York City should be 5 or 6 hours away, respectively, while the truth is that it's 7 hours away.

A few things:
You don't need to make a function for Date.now unless you have to still support IE8, which is rare these days. IE9+ and all major browsers have that function built in.
Date.now() and new Date().getTime() return timestamps based on UTC, not your local time. It doesn't matter which time zone you run it from, it only matters that your computer's clock is synchronized.
The Google Time Zone API also takes its timestamp in terms of UTC, so you are doing the correct thing to pass it along (adjusting milliseconds to seconds).
Google is correctly telling you that for the given timestamp:
The lat/lon coordinates given are in the time zone identified with the America/New_York IANA time zone ID
The English long-form name to display is Eastern Daylight Time
The rawOffset is -18000 seconds, or UTC-5. This field does not include DST, so it is the offset that would be used if Eastern Standard Time were in effect (which it is not for the timestamp given)
There is a dstOffset in effect of 3600 seconds (or 1 hour), which when added to the raw offset gives you (-18000 + 3600 == -14400), or UTC-4
Google is only telling you the offsets from UTC, not from your local time zone. If you wanted to include that, you could call new Date().getTimezoneOffset() (based on the current time) and add that to the result.

Related

Find next occurrence of a time in a non-local timezone (in this case, PST)

I want to get how far away is the next occurence of a particular PST time regardless of the client's timezone.
This would be trivial if the time were in UTC but I don't know how to do it in PST keeping in mind the observance of daylight savings time.
Eg. 4 PM PST would be 11 PM UTC since it is right now summer.
I would prefer not to have to manually input the dates of daylight saving time.
I am happy to use a library if this is not possible without one.
// returns the number of milliseconds from the current time until the specified time in PST.
function getTimeUntil (hour, minutes = 0, seconds = 0)
{
// implementation needed
}
The following is an explanation of why this is likely a duplicate of How to initialize a JavaScript Date to a particular time zone.
PST (presumably US Pacific Standard Time) is a timezone with a fixed offset, UTC -8. Places that observe PST and have daylight saving typically call that offset Pacific Daylight Time (PDT), which is UTC -7.
PST might also be Pitcairn Standard Time, which is also UTC -8 and observed all year round on Pitcairn Island. Converting PST to UTC is achieved by adding 8 hours.
However, likely you want to work with times and dates for a place that observes US PST in winter and US PDT in summer, e.g. Los Angeles. In that case you can use a library like Luxon or date.js that allows creating dates based on a timestamp and specified IANA representative location such as "America/Los_Angeles". If that is the case, then see the link above.
My implementation:
// returns the formatted time from the current time until the specified time in PST.
function getTimeUntil (hour, minutes = 0, seconds = 0)
{
let future = luxon.DateTime.now().setZone('America/Vancouver').set({
hours: hour,
minutes: minutes,
seconds: seconds
});
let now = luxon.DateTime.now().setZone('America/Vancouver');
if (future < now)
{
future = future.plus({ days:1 });
}
return future.diff(now, ["hours", "minutes", "seconds"]);
// implementation needed
}
console.log(getTimeUntil(13, 0, 0).toObject());
<script src="https://cdn.jsdelivr.net/npm/luxon#2.0.1/build/global/luxon.min.js"></script>

Monday and Sunday of previous week in Unix timestamp AND in New Zealand timezone

I was wondering what would be the best way to tackle getting the unix timestamps of Monday and Sunday in New Zealand timezone while the system clock (AWS Lambda) is in a different timezone.
I've tried the below and it seems to work well in my local computer however obviously when executed on AWS, it'll be a different timezone.
Can someone please suggest the best way to deal with timezones so the code can run on whatever location?
var monday = moment().day(-13).startOf('day').toDate().getTime() // Monday last week
var sunday = moment().day(-7).startOf('day').toDate().getTime() // Sunday last week
Unix Timestamp always give time in UTC regardless of your position. To get the local time of your position please apply the timezone offset to the unix timestamp. https://en.wikipedia.org/wiki/Unix_time
A few things:
You can use Moment-Timezone to work with IANA time zone identifiers in Moment.
New Zealand has two different IANA time zone identifiers:
Pacific/Auckland covers most of New Zealand, which uses UTC+12:00 during standard time, and UTC+13:00 during daylight saving time.
Pacific/Chatham covers the Chatham Islands which is also part of New Zealand. However, Chatham uses UTC+12:45 during standard time, and UTC+13:45 during daylight saving time.
You do not need to convert to a Date object. Moment can give you a Unix timestamp directly, either as seconds with .unix(), or as milliseconds with .valueOf(). Both imply a conversion to UTC, as Unix timestamps are inherently UTC based.
One cannot get a Unix timestamp for an entire day, but rather only for a point in time. The timestamp you are probably looking for would be at the start of the local day, which is always midnight (00:00) in New Zealand (but not necessarily in other time zones on DST transition days, depending on the time of the transition).
When use Moment's day function, day(-13) doesn't mean "Monday last week". It means "two Mondays ago." If you meant "one Monday ago", that would be day(-6). Likewise day(-7) means "one Sunday ago. In both cases, it doesn't count the current day. For example, since today is Sunday 2019-09-01, day(-7) refers to Sunday 2019-08-25.
Putting this all together:
var oneMondayAgoInAuckland = moment.tz('Pacific/Auckland').day(-6).startOf('day').valueOf();
var oneSundayAgoInAuckland = moment.tz('Pacific/Auckland').day(-7).startOf('day').valueOf();
At the moment, these return 1566734400000 and 1566648000000 respectively.

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.

Office 365 REST API: Correct for daylight savings time

The Office 365 REST API returns local dates and times with time zones. As the documentation explains, time zones are specified by strings from this standard Windows list of zones. Here's an example of a date/time value returned by the API, in JSON:
{ DateTime: '2016-04-13T08:00:00.0000000',
TimeZone: 'Pacific Standard Time' }
Let's say you want to use this date---for example, to parse it to a JavaScript Date object. You might think that, to parse this date, you'd just need to look up that time zone name in a table to get its offset.
But that's not quite right! Because that date is in April, it's actually specified in daylight time: the appointment it reflects is at 8 AM PDT, not PST, despite all appearances. The date contains no indication of daylight savings time, and "Pacific Daylight Time" isn't even a valid time zone according to that list.
Does the API provide any facilities for getting the real, daylight-sensitive time zone offset for one of these values? Or am I on my own to compensate for DST in my JavaScript client?
Pacific Daylight Time / Pacific Daylight Saving Time are not Time zone (time zone is geography based). The TimeZone property in Office 365 REST API can be set to any of the time zones supported by Windows, as well as the following time zones names.
Etc/GMT+12
Etc/GMT+11
Pacific/Honolulu
America/Anchorage
America/Santa_Isabel
America/Los_Angeles
America/Phoenix
America/Chihuahua
America/Denver
America/Guatemala
America/Chicago
America/Mexico_City
America/Regina
America/Bogota
America/New_York
America/Indiana/Indianapolis
America/Caracas
America/Asuncion
America/Halifax
America/Cuiaba
America/La_Paz
America/Santiago
America/St_Johns
America/Sao_Paulo
America/Argentina/Buenos_Aires
America/Cayenne
America/Godthab
America/Montevideo
America/Bahia
Etc/GMT+2
Atlantic/Azores
Atlantic/Cape_Verde
Africa/Casablanca
Etc/GMT
Europe/London
Atlantic/Reykjavik
Europe/Berlin
Europe/Budapest
Europe/Paris
Europe/Warsaw
Africa/Lagos
Africa/Windhoek
Europe/Bucharest
Asia/Beirut
Africa/Cairo
Asia/Damascus
Africa/Johannesburg
Europe/Kiev
Europe/Istanbul
Asia/Jerusalem
Asia/Amman
Asia/Baghdad
Europe/Kaliningrad
Asia/Riyadh
Africa/Nairobi
Asia/Tehran
Asia/Dubai
Asia/Baku
Europe/Moscow
Indian/Mauritius
Asia/Tbilisi
Asia/Yerevan
Asia/Kabul
Asia/Karachi
Asia/Tashkent
Asia/Kolkata
Asia/Colombo
Asia/Kathmandu
Asia/Almaty
Asia/Dhaka
Asia/Yekaterinburg
Asia/Rangoon
Asia/Bangkok
Asia/Novosibirsk
Asia/Shanghai
Asia/Krasnoyarsk
Asia/Singapore
Australia/Perth
Asia/Taipei
Asia/Ulaanbaatar
Asia/Irkutsk
Asia/Tokyo
Asia/Seoul
Australia/Adelaide
Australia/Darwin
Australia/Brisbane
Australia/Sydney
Pacific/Port_Moresby
Australia/Hobart
Asia/Yakutsk
Pacific/Guadalcanal
Asia/Vladivostok
Pacific/Auckland
Etc/GMT-12
Pacific/Fiji
Asia/Magadan
Pacific/Tongatapu
Pacific/Apia
Pacific/Kiritimati
In this case, the app need to handle it itself which means that you need to compensate for DST in his JavaScript client.

Time Zones in Json Date

I am sending Json data via a REST Service to my client. This client should use the data to Display it.
My client uses JavaScript.
I am converting the date in the following way:
var from = new Date(myJsonDate.match(/\d+/)[0] * 1);
The JSON looks like this:
...="From":"\/Date(1450134000000)\/" ...
My problem is that the dates are correct in Germany but are off by one day in Brazil (e.g. showing Sunday instead of Monday in Brazil).
Does this code use time zones and calculates this accordingly?
How could I turn this off?
I want that the date is displayed exactly how i have sent it.
The operations with dates in JavaScript have a time zone variation in which the client machine is configured.
Right opportunity had to fix a function that showed difference between dates and nobody knew because. When you instance a date, the return her appears as: “Thu Feb 14 2008 08:41:27 GMT-0300 (Official Hour of Brazil)”
Note that in date has the GMT (Greenwich Mean Time) that indicates in which time zone the date is configured.
I’ll show as avoid the difference of time caused by this in operations with date. To this we have create a function that convert the date always to the time zone that if wait.
var calculateTimeZone = function(date, offset) {
var miliseconds_with_utc = date.getTime() + (date.getTimezoneOffset() * 60000);
return new Date(miliseconds_with_utc + (3600000 * offset));
}
Note that in the line 3, we invoke the method getTime() that convert the local moment of date to a number represented by miliseconds since January 1st, 1970 (Unix Epoch). We get the current time zone that is set in browser by method geTimezoneOffset() of API the date in JavaScript and we multiply by miliseconds of time of a hour. We add then the two values.
Why a hour?
Why this is the time that represents each time zone. By default this method return this time zone in minutes, by this the convertion in hour is necessary.
For to arrive this number 60000 you have that remember that 1 second have 1000 miliseconds and which 1 minute have 60 seconds, then converting minutes for miliseconds we multiply 60*1000 = 60000.
This moment we have the UTC (Coordinated Universal Time) represented by variable “utc” by sum of local moment the time zone in miliseconds.
We need now get a date starting this UTC added with the time zone of destiny, how by example a date expressed in time zone +5 transforming in time zone of brazil (Hour of Brazilian).
Note that in line 5 we got an offset (Time Zone Representation) in hour and converting to miliseconds. Remember that here 1 second have 1000 miliseconds and which 1 hour have 3600 seconds, then convert hour in miliseconds should multiply 1000 * 3600 = 3600000.
We add this result with the value of variable “utc” and we got the moment to the time zone wanted. Thenceforth we create a new date with based in long appropriate and return this new date.
In this way we can maintain of integrity desired in application when we need expressed a date in right time zone.
Does this code use time zones and calculates this accordingly?
No. Passing a number to the Date constructor is interpreted as a time value, i.e. milliseconds since 1970-01-01T00:00:00Z. Regardless of the settings of the client, it will create a Date for exactly the same instant in time.
However, by default, Date.prototype.toString uses the host system settings to apply an offset to the displayed values as "local" time.
How could I turn this off?
Modify the script engine. It's part of the ECMAScript standard so any implementation that doesn't do it is non–compliant.
I want that the date is displayed exactly how i have sent it.
Either:
Send it as a plain string, not as a date
Also send the time zone offset of the source so you can apply it at the other end to keep the date the same.
ECMAScript offsets have an opposite sense to most standards, they're -ve for east and +ve for west, so to get a Date with local settings that has the same as the source system:
var d = new Date(timevalue);
d.setMinutes(d.getMinutes() + d.getTimezoneOffset() - sourceTimezoneOffset);
Where sourceTimezoneOffset is the offset of the source system in minutes, +ve for west and -ve for east.
Usually dates related to a specific time zone, so as pointed out, the date in one place might be different to the date in another place at the same instant in time.
If you are not doing any modifications in dates when sending it from server side, the date will be in the timezone where the server is hosted.
So, if your server is hosted in Germany, dates will be in Germany's timezone.
There would be 2 ways to solve this:
Send dates to client in user-timezone from server in the response.
Make adjustments in your client application to implement appropriate
date conversion.

Categories

Resources