Converting Year, Month, Day to momentjs Unix timestamp - javascript

I'm trying to get the same value as 1502755200000 using momentjs
console.log(Date.UTC(2017, (8-1), 15));//1502755200000
var newDate = moment();
newDate.set('year', 2017);
newDate.set('month', 7); // April
newDate.set('date', 15);
console.log(newDate.format('X'));//1502818350
However when I try to get the miliseconds I get 1502818350 Any idea how to get the exact same timestamp as above?
Here is the fiddle https://jsfiddle.net/cdvzoezb/1/

Firstly, .format('X') gives you the unix timestamp in seconds, not milliseconds.
To get milliseconds, you must use .format('x') (lowercase x).
Secondly, when you use moment(), it gives you a moment date object at your current local time, not UTC time. So when you modify it with .set('date', 15) etc, you're setting it to 15 April 2017 in your local time. This is why you're getting the vastly different value.
To get a moment date object for current UTC time, use moment.utc().
Thirdly, the Date object you created will be at time 00:00:00.000, while the moment object will be for current time. So when you set the year/month/date, time still remains at what it was when you created the object. You need to set the moment object's time to 00:00:00.000.
This can be done with the .startOf('day') function.
In conclusion:
console.log(Date.UTC(2017, (8-1), 15)); //1502755200000
var newDate = moment.utc();
newDate.set('year', 2017);
newDate.set('month', 7);
newDate.set('date', 15);
newDate.startOf('day');
console.log(newDate.format('x')); //1502755200000
Or, much shorter:
var newDate = moment.utc('2017-07-15 00:00:00.000');

Well you can simply create a moment object out of a Date instance and then using the utc() to convert the timestamp to UTC. After that, we can use moments method format() to get milliseconds using the x display option like so:
console.log("==============");
console.log(Date.UTC(2017, (8-1), 15));
var base = Date.UTC(2017, (8-1), 15)
var newDate = moment(base);
console.log('a', newDate.utc().format('x')); //1502755200000

Related

Javascript - force new Date constructor to treat argument as UTC

Have an API end point that accepts a date and does some processing. I do give via postman the date as UTC (denoted by the Z at the end). Sample input sent from Postman.
{
"experimentDate":"2022-01-12T12:30:00.677Z",
}
In the code when I do
let startDate = new Date(experimentDate);
//other calculations e.g get midnight of the startDate
startDate.setHours(0,0,0,0);
The first assignment sets startDate corrected to the current timezone. The rest of my calculations go bad as a result of this. For instance when I use the setHours function setting time to 0, I expect it to be at midnight of the UTC time given but it goes to midnight of my current timezone.
Should new Date not keep the date in UTC given that there is a Z at the end of the date?
Should I reconvert it to UTC like below. Is this not redundant?
Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth(),
startDate.getUTCDate(), startDate.getUTCHours(),
startDate.getUTCMinutes(), startDate.getUTCSeconds())
What is the right way to achieve this?
The Date object will be stored as a UTC date, however there are different methods on it that will set/get the date or time for both UTC and local timezones. Try using .setUTCHours(), rather than .setHours().
You can use the Date constructor to parse the timestamp provided.
Most of the methods will treat the date as a local time. For example, the getHours() method returns the hour for the specified date, according to local time.
However you can use the getUTCXXX() methods to get the UTC date components such as year, month, date, hour etc.
You can also use Date.toISOString() to get the date formatted as UTC.
You can use the Date.UTC method to get UTC midnight, passing in the relevant getUTCFullYear(), getUTCMonth(), getUTCDay() etc. from the experiment date.
This can then be passed to the Date constructor.
let timestamp = "2022-01-12T12:30:00.677Z";
const experimentDate = new Date(timestamp);
const midnightUTC = new Date(Date.UTC(experimentDate.getUTCFullYear(), experimentDate.getUTCMonth(), experimentDate.getUTCDate()))
console.log('Experiment date (UTC): ', experimentDate.toISOString());
console.log('Midnight (UTC): ', midnightUTC.toISOString());
You can also use Date.setUTCHours() to do the same thing.
let timestamp = "2022-01-12T12:30:00.677Z";
const experimentDate = new Date(timestamp);
const midnightUTC = new Date(experimentDate);
midnightUTC.setUTCHours(0,0,0,0);
console.log('Experiment date (UTC): ', experimentDate.toISOString());
console.log('Midnight (UTC): ', midnightUTC.toISOString());

Date in Javascript countdown

I am trying to make countdown for website. I have simple javascript code as below. Last line in code gives output 5 where it should give output zero as I have not assigned any hour value to it. And as a result my countdown stops 5 hours late then exact time I want it to stop.
var date1 = new Date("2019-12-09");
document.write(date1.getHours());
You can use getTimezoneOffset() and then subtract it off:
var date1 = new Date("2019-12-09");
console.log(date1.getHours() + date1.getTimezoneOffset() / 60);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
The problem here is that when you create the Date without specifying the timezone, it will treat it as if the hours/minutes/seconds were set to zero and then the whole date was converted to your local timezone (timezone of the browser to be specific). Depending on where you are in the world, it can be many hours off the mark. Because of that, every time you need to compare two dates (either for countown or anything else), you have to either use UTC methods or make sure you specify the timezone on both dates explicitly:
const timeZero = new Date('01 Jan 1970 00:00:00 GMT') // <<- explicit GMT timezone
const isoTimeZero = new Date('1970-01-01T00:00:00.000Z') // ISO format of the same
...
const today = new Date();
const utcDateStr = `${today.getUTCFullYear()}-${today.getUTCMonth()+1}-${today.getUTCDate()} 00:00:00.000 GMT`
const utcDate = new Date(utcDateStr)
const offsetInMillisec = utcDate - timeZero // You can calculate hours/munites left to zero as needed
This example ignores hours/minutes/seconds - they are easy to add in the same fashion as the date. The key is to always use the same timezone for both days, preferably UTC
Alternatively, you may want to consider switching to moment.js and saving yourself lots of hassle :)

show time from milliseconds by using toLocaleTimeString()

I am attempting to show the time using milliseconds. I'm using the toLocaleTimeString since it supports the locale.
var milliseconds = 10000;
var date = new Date(milliseconds);
console.log(date.toLocaleTimeString('en',milliseconds));
// expected result - 0:0:10 AM
// actual result - 5:30:10 AM
The result is not what I'm expected. How can get the expected result using toLocaleTimeString
The normal behaviour of the .toLocaleTimeString() method is to display the time in a string representation based on the local time zone of your environment, that's why you got a different result.
And you were passing a wrong argument milliseconds to it in:
date.toLocaleTimeString('en',milliseconds);
Actually the Date.prototype.toLocaleTimeString() method takes an options object as a second argument, where you can specify several options including the timeZone which specifies the desired time zone for the output.
So call it with {"timeZone": "UTC"} to display it in UTC, like this:
date.toLocaleTimeString('en',{"timeZone": "UTC"})
Demo:
var milliseconds = 10000;
var date = new Date(milliseconds);
console.log(date.toLocaleTimeString('en',{"timeZone": "UTC"}));
// expected result - 0:0:10 AM
// actual result - 5:30:10 AM
In var date = new Date(10000);, the "10000" unit is always relative to 1970-01-01 00:00:00 in UTC timezone (i.e. add 10000ms from it). Thus, the corresponding time is equivalent to 1970-01-01 00:00:10 UTC.
date.toLocaleTimeString('en') output the time in your system timezone, thus gives the difference you found.
One way to fix is to set date variable to system timezone by adding the timezone difference in milliseconds, as the following:
var date = new Date(10000 + new Date().getTimezoneOffset()*60000); (new Date().getTimezoneOffset() is timezone difference in minutes)

JS date calculation with UTC stored on server?

I'm passing back a UTC date from the server, and I need some JS to find the difference in seconds between "now" and the date passed back from the server.
I'm currently trying moment, with something like
var lastUpdatedDate = moment(utcStringFromServer);
var currentDate = moment();
var diff = currentDate - lastUpdatedDate;
problem is, this gives a very invalid answer, because UTC is coming down from the server, and creating a new moment() makes it local. How can I do a calculation with respect to full UTC so it's agnostic of any local timing?
What you aren't quite understanding is that Dates are stored as the number of milliseconds since midnight, Jan 1, 1970 in UTC time. When determining the date/time in the local timezone of the browser, it first works out what the date/time would be in UTC time, then adds/subtracts the local timezone offset.
When you turn a Date back into a number, using +dateVar or dateVar.valueOf() or similar, it is back to the number of milliseconds since 01/01/1970T00:00:00Z.
The nice part about this is that whenever you serialise dates in UTC (either as a number, or as ISO String format), when it gets automatically converted to local time by Javascript's Date object, it is exactly the same point in time as the original value, just represented in local time.
So in your case, when you convert a local date to a number, you get a value of milliseconds in UTC that you are subtracting a value in milliseconds in UTC from. The result will be the number of milliseconds that has passed between the time from the server and the time the new Date() call is made.
Where it gets tricky is when you want a timestamp from the server to not be translated to local time, because you want to show the hours and minutes the same regardless of timezone. But that is not what you need in this case.
Try this way hope it may help:
var lastUpdatedDate = moment(utcStringFromServer);
var date = Date.UTC();
var currentDate = moment(date);
var diff = currentDate - lastUpdatedDate;
I'm assuming that utcStringFromServer is something like this:
Fri, 19 Aug 2016 04:27:27 GMT
If that's the case, you don't really need Moment.js at all. If you pass that string to Date.parse(), it'll return the number of milliseconds since Jan. 1, 1970. You can then use the .toISOString() method to get the same info about right now (converted to UTC) and parse it the same way to get milliseconds since 1970. Then, you can subtract the former from the latter and divide it by 1000 to convert back to seconds.
All in all, it would look something like this:
var lastUpdatedDate = Date.parse(utcStringFromServer);
var currentDate = Date.parse((new Date()).toISOString())
var diff = (currentDate - lastUpdatedDate) / 1000.0; // Convert from milliseconds

Comparing today's date with another date in moment is returning the wrong date, why?

I'm using moment.js 1.7.0 to try and compare today's date with another date but the diff function is saying they are 1 day apart for some reason.
code:
var releaseDate = moment("2012-09-25");
var now = moment(); //Today is 2012-09-25, same as releaseDate
console.log("RELEASE: " + releaseDate.format("YYYY-MM-DD"));
console.log("NOW: " + now.format("YYYY-MM-DD"));
console.log("DIFF: " + now.diff(releaseDate, 'days'));
console:
RELEASE: 2012-09-25
NOW: 2012-09-25
DIFF: 1
Ideas?
Based on the documentation (and brief testing), moment.js creates wrappers around date objects. The statement:
var now = moment();
creates a "moment" object that at its heart has a new Date object created as if by new Date(), so hours, minutes and seconds will be set to the current time.
The statement:
var releaseDate = moment("2012-09-25");
creates a moment object that at its heart has a new Date object created as if by new Date(2012, 8, 25) where the hours, minutes and seconds will all be set to zero for the local time zone.
moment.diff returns a value based on a the rounded difference in ms between the two dates. To see the full value, pass true as the third parameter:
now.diff(releaseDate, 'days', true)
------------------------------^
So it will depend on the time of day when the code is run and the local time zone whether now.diff(releaseDate, 'days') is zero or one, even when run on the same local date.
If you want to compare just dates, then use:
var now = moment().startOf('day');
which will set the time to 00:00:00 in the local time zone.
RobG's answer is correct for the question, so this answer is just for those searching how to compare dates in momentjs.
I attempted to use startOf('day') like mentioned above:
var compare = moment(dateA).startOf('day') === moment(dateB).startOf('day');
This did not work for me.
I had to use isSame:
var compare = moment(dateA).isSame(dateB, 'day');

Categories