29

I am currently using Moment js to parse an ISO 8601 string into date and time, but it is not working properly. What am I doing wrong? And I would take any other easier solutions as well.

The ISO 8601 I would like to parse: "2011-04-11T10:20:30Z" into date in string: "2011-04-11" and time in string: "10:20:30"

And tried console.log(moment("2011-04-11T10:20:30Z" ,moment.ISO_8601)) and console.log(moment("2011-04-11T10:20:30Z" , ["YYYY",moment.ISO_8601]) as a test, but it just returns an object with all different kinds of properties.

Walter
  • 661
  • 3
  • 8
  • 15

2 Answers2

56

With moment.js

var str = '2011-04-11T10:20:30Z';
var date = moment(str);
var dateComponent = date.utc().format('YYYY-MM-DD');
var timeComponent = date.utc().format('HH:mm:ss');
console.log(dateComponent);
console.log(timeComponent);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>

Or simply with string manipulation

var str = '2011-04-11T10:20:30Z';
var parts = str.slice(0, -1).split('T');
var dateComponent = parts[0];
var timeComponent = parts[1];
console.log(dateComponent);
console.log(timeComponent);
Xotic750
  • 20,394
  • 8
  • 50
  • 71
  • You do realize that you're using raw Javascript date logic so that you can use a higher order date processing library? That's rather like using `$(document.getElementById('foo'))`; it works, but most people would use the tool throughout the process (`$('#foo')`). Similarly here, this answer works, but you're losing a lot of the benefit Moment gives you by doing string and date parsing manually. IMHO you'd be better served in the long run by learning how to use your tool (Moment) than abandoning it. – machineghost Sep 28 '16 at 01:10
  • 1
    Who knows what the OPs intention is for the two strings? I wouldn't load a library to change the `className` on an element referenced by an `id`, if that was the only thing that was needed. Use the correct tool for the job, but keep it simple. – Xotic750 Sep 28 '16 at 01:29
18

There's two parts to the moment operation: reading the date/time in, and spitting it back out. You've got the first part:

moment("2011-04-11T10:20:30Z")

but then you need to call an output function, eg:

moment("2011-04-11T10:20:30Z").format('YYYY-MM-DD h:mm:ss a')
machineghost
  • 28,573
  • 26
  • 128
  • 197
  • Thank you for the response. Currently it is console logging: `2011-04-11 3:20:30 am`. So the date is correct but the hour is wrong. Shouldn't it be hh:mm:ss? Tried it but still comes out to be 03 rather than 10. – Walter Sep 28 '16 at 00:07
  • 1
    You can find a full breakdown of all of the formatting patterns here: http://momentjs.com/docs/#/displaying/. However, I don't think the time is a formatting problem; I'm pretty sure it's a timezone issue. Your initial date string lacks a timezone bit, so Moment decides to interpret it as some time zone (I'd guess 0 GMT), then shows you the time relative to your current time zone (I'd guess you live +/- 7 from GMT?). You'll want to read the Moment docs (or perhaps ask a separate question) on timezones to resolve this. – machineghost Sep 28 '16 at 00:13
  • As a side note, timezones are one of the most annoying things about Moment, and I often wish they'd paper over them ... but ultimately as a web developer I'm glad they don't. Some of your users will almost certainly use your site in a different time zone from you, so it's important that you think through how you store dates on your server, and then how your JS/Moment code localizes them when you display them to the user. – machineghost Sep 28 '16 at 00:17
  • I'm currently in PST. Before I accept the answer and upvote, could you possibly show an example with the exact format I'm trying to get at with timezone modification? Date string: `"2011-04-11"` and time string: `"10:20:30"` I looked at the docs but didn't help much. – Walter Sep 28 '16 at 00:25
  • 1
    You have four options for the *hours* part of the datetime string. Let's assume the time is 1pm: `h` = "1" ... `hh` = "01" ... `H` = "13" ... `HH` = "13". Those last two are the same for 1pm, but if we switch to 1am they become: `H` = "1" ... `HH` = "01". In other words, capitalization controls whether the time is 12-based or 24-based, and two letters signifies that Moment will pad the time with "0". I can't tell from your question whether you want padding or not, or whether you want 12- or 24-hour time, because you picked 10 as an example (and it's the same in all four formats). – machineghost Sep 28 '16 at 00:33
  • The data does have a timezone element: `Z`. Which is UTC. You are missing this: http://momentjs.com/docs/#/parsing/utc/ – Xotic750 Sep 28 '16 at 00:36
  • Oh right. Well everything I said is still correct, as UTC 0 is GMT. The point being that @Walter is bringing the date in from that time zone, but when he formats it Moment does the timezone math to translate it to his timezone. – machineghost Sep 28 '16 at 00:38
  • @machineghost Sorry for the misconfusion then. Hopefully this is a better example: "2011-04-11T00:20:30Z". So do want the padding and in 24-hour time. Also the day is always off by 1, so 11 would come out to be 10 and 7 would be 6. What would be a way to fix that? – Walter Sep 28 '16 at 00:40
  • @Xotic750 No worries. Clarified more in the previous comment – Walter Sep 28 '16 at 00:41
  • 0-padded 24-hour time is `HH`, so there you go :) As for the day, I suspect it's related to the timezone issue (remember, 1AM today is 11AM yesterday to someone two timezones away). Fix your timezone and it should fix both the day and hour issues (and by "fix" I mean either have your server translate all dates in to GMT/UTC 0 timezone before Moment sees them, or use `http://momentjs.com/timezone/` to tell Moment what timezone the time came from; personally I recommend the former, as it simplifies things all around if your server just keeps all times in GMT). – machineghost Sep 28 '16 at 00:41
  • @machineghost Just tried `HH` and it gave me 17:20:30 when it should be 00:20:30. And could you clarify on fixing the timezone? Am I supposed to specify it in `moment`? Also didn't @Xotic750 mention that Z is in fact timezone? I simply want to print it out exactly how the ISO 8601 string is passed in. – Walter Sep 28 '16 at 00:44
  • See above (I edited my comment). The key thing I think you're missing is that when you tell Moment `"10:20:30"` you are not saying "10:20:30 in my timezone", you are telling it "10:20:30 in GMT/UTC 0" (ie. "10:20:30 in Great Britain"). If you want "10:20:30" in your timezone, you either first need to convert it to GMT before Moment gets it, or (after Moment gets it) you need to tell Moment to translate it (with Moment timezone). But again, just overall for your app things will probably be simpler if your server can just store times in UTC 0/GMT time. – machineghost Sep 28 '16 at 00:46