Get ISOString in microseconds from unix timestamp - javascript

I have a epoch/unix timestamp which I have, which I get after running the journalctl -o json-pretty -f command. So I get my "__REALTIME_TIMESTAMP" : "1576681153604871" value from a given log. I want to convert this to an ISOString format, so I use the below code
var result;
time = parseInt(time);
var msec = time/1000; // convert __REALTIME_TIMESTAMP to milliseconds from microseconds
var myDate = new Date(msec);
var isoDate = myDate.toISOString();
I get the output as below
"2019-12-18T14:25:49.605Z"
I wish to even display the microsecond part in this something like
"2019-12-18T14:25:49.605762Z"
but myDate.toISOString() doesn't work properly if I don't convert the epoch to milliseconds.
I dont know if time % 1000 is the right way, to extract the microsecond part and then append it to get the desired output .
So is there a way to get the output in microsecond format ?

So is there a way to get the output in microsecond format ?
Not using built–in methods. You can add the microsecond part yourself though. It's best to use string methods to get the digits to preserve leading zeros:
// Time value in microseconds
let tv = 1576681153064071;
// Get millisecond part
let msec = tv/1000;
// Get microsecond part - keep leading zeros
let μsec = String(tv).slice(-3);
// Get ISO 8601 timestamp
let isoDate = new Date(msec).toISOString();
// Add in microseconds
let isoDatePlus = isoDate.replace('Z', μsec + 'Z');
console.log(isoDatePlus);
It might be better to replace the entire decimal part though, just in case some future implementation decides to add more digits after the decimal place.
let tv = 1576681153064071;
let isoDate = new Date(tv/1e3).toISOString().replace(/\d+Z$/, String(tv).slice(-6) + 'Z');
console.log(isoDate);

Modifying #RobG's example, the technically correct and faster code would be
let tv = 1576681153064071;
let isoDate = new Date(tv/1e3).toISOString().slice(0, -4) + String(tv).slice(-6).padStart(6, '0') + 'Z';
console.log(isoDate);
// Less than 6 digits microseconds example
let smallTs = 50
console.log(new Date(smallTs/1e3).toISOString().slice(0, -4) + String(smallTs).slice(-6).padStart(6, '0') + 'Z');
RobG example cannot convert smaller than 6 Digits microseconds like 500 or 50 to ISO String correctly. Thank you for your answer though.

Related

Issues parsing a string-date React/JS

For example, I have this string "2020-09-09T21:00:14.114-04:00"
I grab this from my database and in its current form, it is a string. my goal is to have it display
4 PM instead of the long string of jibberish
is it possible to accomplish this?
I was thinking of possibly creating a new date object like
let test = new Date('2020-09-09T21:00:14.114-04:00').
but I'm stuck at the parsing and formatting part. it would be better to have this be done while the current state is a string but I don't think that this would be possible
edit: i would like the desired output to be the hour:minute and then am/pm
ex 10:15pm
You can do that by parsing the date from your database using Date.parse().
Then you can get the time or whatever you need using date.toLocalTimeString() in your case.
let dateUnix = Date.parse('2020-09-09T21:00:14.114-04:00');
const time = new Date(dateUnix).toLocaleTimeString();
console.log(time); // --> "4:00:14 AM"
The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognized or, in some cases, contains illegal date values (e.g. 2015-02-31).
Here's some useful resources MDN Date.parse()
MDN Date.toLocalTimeString()
You can do as following way.new Date() is used to get the current date and time.
var today = new Date();
var time = today.getHours();
if(time>12){
var new_time= time % 12;
}
else{
var new_time= time;
}

MomentJS Parsing Unix Timestamp Sent Through GET Request Incorrectly

I have an array of 2 strings, both of which are in Unix time.
[1484930449590,1548002449590]
Converting these back into human readable time gives me today's date and the date 2 years ago.
However, when I parse both of these timestamps with MomentJS:
const start = moment(timeRange[0])
const end = moment(timeRange[1])
I receive the following values:
moment("2001-01-01T00:00:00.000")
moment("2001-04-01T00:00:00.000")
For some reason, momentJS converts both of the timestamps to the year 2001, even though the years should be 2019 and 2017.
Parsing the strings first does not make things better:
const start = moment(parseInt(timeRange[0]))
const end = moment(parseInt(timeRange[1]))
Now start and end are:
moment("1969-12-31T19:00:00.001")
moment("1969-12-31T19:00:00.004")
Does anyone know what is going on?
I tried the following solution:
console.log(timeRange)
const start = moment(parseInt(timeRange[0]) / 1000)
console.log(start)
const end = moment(parseInt(timeRange[1]) / 1000)
console.log(end)
but nothing changed:
1484931697215,1548003697215
moment("1969-12-31T19:00:00.000")
moment("1969-12-31T19:00:00.000")
Update:
The issue is that I was wrong about timeRange being an array. Rather, it was actually a string. This happened because on the client-side timeRange was an array, but when it got sent as a GET request to the server and retrieved with const timeRange = req.query.timeRange, it got converted to a string.
Your timestamp is in milliseconds, not in seconds. Try dividing by 1000 first:
const start = moment(parseInt(timeRange[0]/1000))
const end = moment(parseInt(timeRange[1]/1000))
That should give you the correct date
The issue is that I was wrong about timeRange being an array. Rather, it was actually a string. This happened because on the client-side timeRange was an array, but when it got sent as part of a GET request to the server and retrieved with const timeRange = req.query.timeRange, it got converted to a string.
The solution was to reconvert the timeRange back into an array:
const times = req.query.timeRange.split(",")
const startDate = moment(parseInt(times[0]))
const endDate = moment(parseInt(times[1]))

Incorrect time while copy pasting a date time value using google apps script [duplicate]

I'm trying to get from a time formatted Cell (hh:mm:ss) the hour value, the values can be bigger 24:00:00 for example 20000:00:00 should give 20000:
Table:
if your read the Value of E1:
var total = sheet.getRange("E1").getValue();
Logger.log(total);
The result is:
Sat Apr 12 07:09:21 GMT+00:09 1902
Now I've tried to convert it to a Date object and get the Unix time stamp of it:
var date = new Date(total);
var milsec = date.getTime();
Logger.log(Utilities.formatString("%11.6f",milsec));
var hours = milsec / 1000 / 60 / 60;
Logger.log(hours)
1374127872020.000000
381702.1866722222
The question is how to get the correct value of 20000 ?
Expanding on what Serge did, I wrote some functions that should be a bit easier to read and take into account timezone differences between the spreadsheet and the script.
function getValueAsSeconds(range) {
var value = range.getValue();
// Get the date value in the spreadsheet's timezone.
var spreadsheetTimezone = range.getSheet().getParent().getSpreadsheetTimeZone();
var dateString = Utilities.formatDate(value, spreadsheetTimezone,
'EEE, d MMM yyyy HH:mm:ss');
var date = new Date(dateString);
// Initialize the date of the epoch.
var epoch = new Date('Dec 30, 1899 00:00:00');
// Calculate the number of milliseconds between the epoch and the value.
var diff = date.getTime() - epoch.getTime();
// Convert the milliseconds to seconds and return.
return Math.round(diff / 1000);
}
function getValueAsMinutes(range) {
return getValueAsSeconds(range) / 60;
}
function getValueAsHours(range) {
return getValueAsMinutes(range) / 60;
}
You can use these functions like so:
var range = SpreadsheetApp.getActiveSheet().getRange('A1');
Logger.log(getValueAsHours(range));
Needless to say, this is a lot of work to get the number of hours from a range. Please star Issue 402 which is a feature request to have the ability to get the literal string value from a cell.
There are two new functions getDisplayValue() and getDisplayValues() that returns the datetime or anything exactly the way it looks to you on a Spreadsheet. Check out the documentation here
The value you see (Sat Apr 12 07:09:21 GMT+00:09 1902) is the equivalent date in Javascript standard time that is 20000 hours later than ref date.
you should simply remove the spreadsheet reference value from your result to get what you want.
This code does the trick :
function getHours(){
var sh = SpreadsheetApp.getActiveSpreadsheet();
var cellValue = sh.getRange('E1').getValue();
var eqDate = new Date(cellValue);// this is the date object corresponding to your cell value in JS standard
Logger.log('Cell Date in JS format '+eqDate)
Logger.log('ref date in JS '+new Date(0,0,0,0,0,0));
var testOnZero = eqDate.getTime();Logger.log('Use this with a cell value = 0 to check the value to use in the next line of code '+testOnZero);
var hours = (eqDate.getTime()+ 2.2091616E12 )/3600000 ; // getTime retrieves the value in milliseconds, 2.2091616E12 is the difference between javascript ref and spreadsheet ref.
Logger.log('Value in hours with offset correction : '+hours); // show result in hours (obtained by dividing by 3600000)
}
note : this code gets only hours , if your going to have minutes and/or seconds then it should be developped to handle that too... let us know if you need it.
EDIT : a word of explanation...
Spreadsheets use a reference date of 12/30/1899 while Javascript is using 01/01/1970, that means there is a difference of 25568 days between both references. All this assuming we use the same time zone in both systems. When we convert a date value in a spreadsheet to a javascript date object the GAS engine automatically adds the difference to keep consistency between dates.
In this case we don't want to know the real date of something but rather an absolute hours value, ie a "duration", so we need to remove the 25568 day offset. This is done using the getTime() method that returns milliseconds counted from the JS reference date, the only thing we have to know is the value in milliseconds of the spreadsheet reference date and substract this value from the actual date object. Then a bit of maths to get hours instead of milliseconds and we're done.
I know this seems a bit complicated and I'm not sure my attempt to explain will really clarify the question but it's always worth trying isn't it ?
Anyway the result is what we needed as long as (as stated in the comments) one adjust the offset value according to the time zone settings of the spreadsheet. It would of course be possible to let the script handle that automatically but it would have make the script more complex, not sure it's really necessary.
For simple spreadsheets you may be able to change your spreadsheet timezone to GMT without daylight saving and use this short conversion function:
function durationToSeconds(value) {
var timezoneName = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
if (timezoneName != "Etc/GMT") {
throw new Error("Timezone must be GMT to handle time durations, found " + timezoneName);
}
return (Number(value) + 2209161600000) / 1000;
}
Eric Koleda's answer is in many ways more general. I wrote this while trying to understand how it handles the corner cases with the spreadsheet timezone, browser timezone and the timezone changes in 1900 in Alaska and Stockholm.
Make a cell somewhere with a duration value of "00:00:00". This cell will be used as a reference. Could be a hidden cell, or a cell in a different sheet with config values. E.g. as below:
then write a function with two parameters - 1) value you want to process, and 2) reference value of "00:00:00". E.g.:
function gethours(val, ref) {
let dv = new Date(val)
let dr = new Date(ref)
return (dv.getTime() - dr.getTime())/(1000*60*60)
}
Since whatever Sheets are doing with the Duration type is exactly the same for both, we can now convert them to Dates and subtract, which gives correct value. In the code example above I used .getTime() which gives number of milliseconds since Jan 1, 1970, ... .
If we tried to compute what is exactly happening to the value, and make corrections, code gets too complicated.
One caveat: if the number of hours is very large say 200,000:00:00 there is substantial fractional value showing up since days/years are not exactly 24hrs/365days (? speculating here). Specifically, 200000:00:00 gives 200,000.16 as a result.

How do I get difference between two dates of unknown format in javascript?

I get a date as String from server like this: 2017-01-23T16:08:45.742Z. I want to find the difference in days, between this and the current date (or precisely, current time). I could just extract date alone (without time) and check, but I'd need a precise answer based on provided time & current time.
How do I achieve this?
Should be easy....
var dateFromServer = '2017-01-23T16:08:45.742Z'
var msInDay = 1000 * 60 * 60 * 24
var difference = (new Date(dateFromServer) - Date.now()) / msInDay
document.write('difference = ' + difference + ' days')
That date format looks like ISO_8061. https://en.wikipedia.org/wiki/ISO_8601
Use the Date object to get the difference between today and the other date in milliseconds, then divide by the number of milliseconds in a day.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
The code below can be condensed into a single line but I wanted to be explicit.
let date = "2017-01-23T16:08:45.742Z";
let d1 = new Date(date); // given date
let today = new Date(); // today's date
let diff = (d1 - today); // difference in milliseconds
let days = diff / 8.64e+7; // divide difference by 1 day in milliseconds
console.log(days)
Point of clarification: if I understand you correctly, you're actually trying to get the difference between two dates of different formats, not two dates of unknown formats. That's way easier.
Further, it looks like your server string is already stored in ISO format, which again makes this way easier.
I'd recommend looking at the JavaScript Date object. I believe in this case your best bet would be something like this:
// Your string from the server
var data_from_server = '2017-01-23T16:08:45.742Z';
// Create a new Date() object using the ISO string provided by your server
var olddate = new Date(data_from_server);
// Create a new empty Date() object, which should default to the current time
var currentdate = new Date();
// Subtract the two
var dif = currentdate.getTime() - olddate.getTime();
// Alert the result
alert(dif);

What is a good way to convert %H:%M:%S strings to timespan?

I have a data set with most of the data points in H:M:S format, such as 20:59:59, showing the time span used by individual athletes at different laps.
With D3.js, what is the best way to convert it to time spans, i.e. number of seconds?
I tried parser = d3.timeParse("%H:%M:%S"); but it seems to be very wrong..
If you are using D3 3.x, then you can construct a suitable parser with:
var parser=d3.time.format("%H:%M:%S");
or if you were using D3 4.x:
var parser=d3.timeParse("%H:%M:%S");
Either way, you would then be able to convert your data points into JS Date objects like this:
var t1 = parser.parse("20:59:59");
var t2 = parser.parse("21:02:13");
You can find out the elapsed time between these two time instances by subtracting, eg:
var elapsed = t2 - t1; /* Returns 134000 = 134 seconds */
elapsed will be the number of elapsed milliseconds.
The reason that works is that Date objects provide a valueOf() method which returns the number of milliseconds elapsed since Jan 1 1970. Subtracting the date objects automatically calls valueOf() and subtracts the returned values.
Note that if the time strings you are parsing do not include a date portion, then you will have problems if the starting time and ending time are not in the same day.
EDIT:
From the comments it becomes clear that the times you are working with are already lap durations, in H:M:S format, and you want to convert them to seconds. That does not require D3, it is easy enough:
var components = /^(\d+):(\d+):(\d+)$/.exec("20:59:59");
var elapsedSecs = components[1]*3600+components[2]*60+components[3];
You can use d3.time.format("%H:%M:%S") for your conversion.

Categories