Using momentjs to convert date to epoch then back to date

I'm trying to convert a date string to epoch, then epoch back to the date string to verify that I'm providing the correct date string.

var epoch = moment("10/15/2014 9:00").unix(); // do I need to do .local()?
var momentDate = moment(epoch); // I've also tried moment.utc(epoch) 
var momentDateStr = momentDate.calendar();
alert("Values are: epoch = " + epoch + ", momentDateStr = " + momentDateStr);

Renders

Values are: epoch = 1413378000, momentDateStr = 01/17/1970

Note: I'm using the following version of the moment js script, //cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment-with-locales.js


Solution 1:

There are a few things wrong here:

  • First, terminology. "Epoch" refers to the starting point of something. The "Unix Epoch" is Midnight, January 1st 1970 UTC. You can't convert an arbitrary "date string to epoch". You probably meant "Unix Time", which is often erroneously called "Epoch Time".

  • .unix() returns Unix Time in whole seconds, but the default moment constructor accepts a timestamp in milliseconds. You should instead use .valueOf() to return milliseconds. Note that calling .unix()*1000 would also work, but it would result in a loss of precision.

  • You're parsing a string without providing a format specifier. That isn't a good idea, as values like 1/2/2014 could be interpreted as either February 1st or as January 2nd, depending on the locale of where the code is running. (This is also why you get the deprecation warning in the console.) Instead, provide a format string that matches the expected input, such as:

    moment("10/15/2014 9:00", "M/D/YYYY H:mm")
    
  • .calendar() has a very specific use. If you are near to the date, it will return a value like "Today 9:00 AM". If that's not what you expected, you should use the .format() function instead. Again, you may want to pass a format specifier.

  • To answer your questions in comments, No - you don't need to call .local() or .utc().

Putting it all together:

var ts = moment("10/15/2014 9:00", "M/D/YYYY H:mm").valueOf();
var m = moment(ts);
var s = m.format("M/D/YYYY H:mm");
alert("Values are: ts = " + ts + ", s = " + s);

On my machine, in the US Pacific time zone, it results in:

Values are: ts = 1413388800000, s = 10/15/2014 9:00

Since the input value is interpreted in terms of local time, you will get a different value for ts if you are in a different time zone.

Also note that if you really do want to work with whole seconds (possibly losing precision), moment has methods for that as well. You would use .unix() to return the timestamp in whole seconds, and moment.unix(ts) to parse it back to a moment.

var ts = moment("10/15/2014 9:00", "M/D/YYYY H:mm").unix();
var m = moment.unix(ts);

Solution 2:

http://momentjs.com/docs/#/displaying/unix-timestamp/

You get the number of unix seconds, not milliseconds!

You you need to multiply it with 1000 or using valueOf() and don't forget to use a formatter, since you are using a non ISO 8601 format. And if you forget to pass the formatter, the date will be parsed in the UTC timezone or as an invalid date.

moment("10/15/2014 9:00", "MM/DD/YYYY HH:mm").valueOf()