Node process.hrtime() is five years off? - javascript

I'm using Node v16.17 on MacBook Pro M1.
I want to use microsecond timestamps, so I tried process.hrtime().
But this is very strange, as the first array element (which should be seconds when multiplied by 1000) is like some date in 2017:
> new Date().getTime();
1669997280728
> process.hrtime();
[ 1486038, 90680583 ]
So, if I take 1486038000 --> it is Thu, 02 Feb 2017 12:20:00 GMT
If I take out the milliseconds from new Date().getTime() -> it is correctly Fri, 02 Dec 2022 16:08:00 GMT
What it the issue here? I thought process.hrtime() will be the high resolution time, but why is this so off?
Thanks
Fritz

Per the docs,
These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift. The primary use is for measuring performance between intervals
https://nodejs.org/api/process.html#processhrtimetime
It is only a coincidence that you got a somewhat relevant date.
You should be using process.hrtime.bigint(), however, because process.hrtime() has been legacy for a while (even in Node v16.17).

What?
process.hrtime() has nothing do to with the real-time clock, as is explained by the docs:
These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift.
(emphasis mine)
And,
The primary use is for measuring performance between intervals:

Related

How to adjust an array of hours to a preferred timezone?

So a little context, I have an array of 24 arrays -- one for every hour in the day.
So midnight, 0 index, would be [133.00, 234.00] which would indicate 133 actions from 12 - 1230 and 234 actions between 1230 - 1am.
I need to adjust these indexed arrays to account for the user's timezone in a browser with JS, so that if the user is in New York the 0 index (midnight in the user's home turf) is displayed in China's offset (12pm tomorrow, from user's perspective).
I've been trying to think of a solution, I have a simple function for what I've been able to think of
function offsetHourIndex(hourIndex, dataCenterTimeZone) {
let userTime = new Date().setHour(hourIndex)
return moment(userTime).tz(dataCenterTimeZone).hour();
}
How reliable would this approach be?
Your approach has a few problems:
You are assuming that the current date in the local time zone is the correct date for the target time zone. Most of the time, there are two dates active somewhere around the world. For example, 2019-04-02 04:00 in London is 2019-04-01 23:00 in New York. If you just take hour 4 from London but apply it to the current date in New York, you've created a whole new point in time, a day too early.
You assume there will be exactly 24 hours in every day. In time zones that have transitions for daylight saving time or changes in standard time, you may have more or less hours of local time on a the day of the transition.
In the case of a backward transition, there is a period of ambiguous local time. For example, when US Pacific Time moves from PDT to PST in November, the hour from 1:00-1:59 is repeated. If data from both hours are summarized into array element 1, then you will have higher than normal results for that hour. The opposite is true for forward transitions - you will have an hour with no data.
The time zone setting of the server can be a fickle thing. What if you change data centers? What if you move to the cloud? What if you are operating multiple data centers? What if a server administrator thinks all they are affecting by changing the system time zone is the readout on the taskbar or front panel, etc., and then it affects your application? In general one should avoid these things by never relying on the server's local time zone setting.
You can avoid all of these problems by basing everything on Coordinated Universal Time (UTC) - especially the array. Then you can be ignorant of any server time zone setting, and just base everything off the current UTC day, which is the same all over the world.
This will give you the local hour from the given UTC hour in your index:
var localHour = moment.utc({hour: hourIndex}).local().hour();
You do not need moment-timezone for the above recommendation.
However, if you really feel like you need to convert from a specific time zone to the browser local time, then you would use moment-timezone like this:
var localHour = moment.tz({hour: hourIndex}, timeZoneName).local().hour();
Note when you do this, you also have another problem - not every time zone is offset by a whole number of hours. For example, India uses UTC+05:30. There are many that are :30 and a few that are :45. By tracking hours only, you're not providing enough information to properly convert to the correct local hour. Your results may be off by one.
It seems reasonable. And the code should work as long as you have the properly formatted inputs. I like the brevity and clarity of the function. Any reason you are concerned about reliability?
You might mention in your question that you are using the moment and moment-timezone packages here to derive your data via its functions (moment & tz) on this line of code:
return moment(userTime).tz(dataCenterTimeZone).hour();
Your function may appear a bit cryptic without the imports in your example for folks reading here to understand, such as :
import * as moment from 'moment';
import 'moment-timezone';

where are the leap seconds in javascript?

When I use
a custom zoneinfo file for TAI or /usr/share/zoneinfo-leaps and
a modified NTP client (currently it just adds 27 seconds; and waits for a time stamp that is about 1 second off)
on my ArchLinux box,
the system time behaves nicely:
> date
Tue Oct 23 17:10:34 TAI 2018
> date -d #1483228827
Sun Jan 1 00:00:00 UTC 2017
> date -d #1483228826
Sat Dec 31 23:59:60 UTC 2016
> date -d #1483228825
Sat Dec 31 23:59:59 UTC 2016
but: JavaScript does not:
test page
screenshot
Does Mozilla/Firefox/Javascript use its own zoneinfo files
somewhere?
How can i fix it?
Not even websites dedicated to time seem to get it right... Or am i missing something?
-arne
The JavaScript Date object specifically adheres to the concept of Unix Time (albeit with higher precision). This is part of the POSIX specification, and thus is sometimes called "POSIX Time". It does not count leap seconds, but rather assumes every day had exactly 86,400 seconds. You can read about this in section 20.3.1.1 of the current ECMAScript specification, which states:
Time is measured in ECMAScript in milliseconds since 01 January, 1970 UTC. In time values leap seconds are ignored. It is assumed that there are exactly 86,400,000 milliseconds per day.
JavaScript is not unique in this regard. This is what the vast majority of other languages do, including Python, Ruby, .NET, the typical implementation of time_t in C, and many others.
Because you have altered your system to track TAI instead of UTC, and there is an implementation of a leap second table on your system that the date command understands, then on your system time_t isn't a Unix timestamp, but rather a TAI-based variant masquerading as a Unix timestamp. Just because the date command and the other underlying functions recognize this, doesn't mean that carries through to all platforms and runtimes on your machine.
The fact is, that the unpredictable nature of leap seconds makes them very difficult to work with in APIs. One can't generally pass timestamps around that need leap seconds tables to be interpreted correctly, and expect that one system will interpret them the same as another. For example, while your example timestamp 1483228826 is 2017-01-01T00:00:00Z on your system, it would be interpreted as 2017-01-01T00:00:26Z on POSIX based systems, or systems without leap second tables. So they aren't portable. Even on systems that have full updated tables, there's no telling what those tables will contain in the future (beyond the 6-month IERS announcement period), so I can't produce a future timestamp without risk that it may eventually change.
To be clear - to support leap seconds in a programming language, the implementation must go out of its way to do so, and must make tradeoffs that are not always acceptable. Though there are exceptions, the general position is to not support them - not because of any subversion or active countermeasures, but because supporting them properly is much, much harder.
That said, there is hope for you if you really care about leap seconds in JavaScript. You can add your thoughts to TC39 Temporal proposal (of which I am one of the champions). This won't change the behavior of the Date object - that is baked and has been for decades. But we are developing a new set of standard objects for date and time in JavaScript, and would love your feedback and participation. There is a thread where we have been considering various ways that leap seconds could be part of this in issue #54. At the moment, we haven't put much thought into TAI-based systems. If this is an area that you have experience in, please add your thoughts there. Keep in mind we'll need to balance this with the general needs of the community, but we'd like your thoughts. Thanks!

Javascript Date Gives me EDT but I want EST

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:

Daylight Savings Time wrongly identified by Node.js

I'm having an issue with timezones, DST and Node.js. It doesn't identify correctly DST effects. My OS is Windows 8.1 and have the timezone value and DST well set. I tried these two methods:
1) Node's Date Object
I typed the following code in Node Prompt and received the answer in italic:
new Date()
Tue Sep 09 2014 18:42:36 GMT-0200 (Horário brasileiro de verão(Brazilian Daylight Savings Time))
However, the brazilian DST starts just in Oct 19th, we are not in DST right now. Therefore, the hour is shifted 1 hour from now.
2) node-time
I got node-time package from npm, to be able to change Timezone. In the code:
time = require('time');
dateFormat = require('dateformat');
now = time.Date();
console.log(dateFormat(now.setTimezone('America/Sao_Paulo').getTime(), "yyyy-mm-dd HH:MM:ss Z"))
and as a result, I got
2014-09-09 18:42:36 GMT-0200
Brazilian normal timezone is GMT-0300. Hour is also 1 hour shifted.
Am I doing something wrong? Is there a workaround?
The node-time package does not work on Windows. I couldn't even get it installed, so I'm not sure how you did. You should uninstall it.
If you need support for non-local time zones in Node (or in the browser), I recommend moment.js with the moment-timezone plugin.
Running new Date() on Windows with the time zone set for Brazil, I get the correct output.
The only thing that would explain your results is if the time zone registry settings were modified - but then you'd also see the wrong time in your system clock on your taskbar. So I'm sorry, but I cannot reproduce that part of it.

Daylight Saving Time in Javascript for 1974?

"During the "energy crisis" years, Congress enacted earlier starting dates for daylight time. In 1974, daylight time began on 6 January and in 1975 it began on 23 February. After those two years the starting date reverted back to the last Sunday in April. "
(via http://aa.usno.navy.mil/faq/docs/daylight_time.php )
There appears to be a bug in the Javascript date object for these dates. If you convert 127627200000 milliseconds to a date, it should be Thu Jan 17 00:00:00 EDT 1974. This is correct on http://www.fileformat.info/tip/java/date2millis.htm, but incorrect on
http://www.esqsoft.com/javascript_examples/date-to-epoch.htm, which says it converts to Wed Jan 16 1974 23:00:00 GMT-0500 (Eastern Standard Time). If you create a new Date(127627200000) object in javascript, it gives the latter date conversion. This happens in all major browsers.
I can't imagine this is first time this has been a problem for anyone, but I can't find any other cases of this problem with a few searches online. Does anyone know if there is an existing fix for this or an easier fix than manually checking the dates Javascript has the conversion wrong? Are there other dates this is a problem?
As ever, it's best to check the spec :)
In this case, I was pretty shocked to see this in section 15.9.1.9 of ECMA-262:
The implementation of ECMAScript
should not try to determine whether
the exact time was subject to daylight
saving time, but just whether daylight
saving time would have been in effect
if the current daylight saving time
algorithm had been used at the time.
This avoids complications such as
taking into account the years that the
locale observed daylight saving time
year round.
In other words, a conformant ECMAScript implementation is not allowed to be historically accurate.
Now whether all implementations follow this or not, I'm not sure... but it does suggest you'd need some kind of separate library if you wanted to get historically accurate time zones... where "historically accurate" doesn't have to be nearly as far back as 1974, of course: the US changed its DST schedule in 2007, and other countries have done so more recently than that (and with less warning).
1 The first occurrence of 15.9.1.9. For some reason it occurs twice - once for "Daylight Saving Time Adjustment" and once for "Local Time". Wow.
Java does historical time zones (back to about 1920), JavaScript apparently does not.

Categories