21

Given the volume of Timezone questions, I would have thought to be able to find the answer to this issue, but haven't had any success.

Is there a way using moment.js to parse an ISO-8601 string but have it parsed in my local timzeone? Essentially I want to ignore the timezone information that is supplied in the ISO string.

For example, if I am in EDT timezone:

var x = moment( "2012-12-31T00:00:00+0000" );

will give me: "2012-12-30T19:00:00-5000"

I'm looking to ignore the timezone info and just have it give me a moment equivalent of "2012-12-31T00:00:00-5000" local time (EDT).

Eric B.
  • 23,425
  • 50
  • 169
  • 316

10 Answers10

14

I solved this by supplying a format as the second argument, and using Moment's method of escaping characters, and wrapped square brackets around the timezone.

moment("2016-01-01T05:00:00-05:00", "YYYY-MM-DDTHH:mm:ss[Z]").startOf("hour").format()

This will still create moment objects using your local time zone, but it won't do any sort of auto-timezone calculation. So the above example will give you 5am regardless of timezone supplied.

Mark
  • 1,564
  • 1
  • 14
  • 22
13

I don't think you really want to ignore the offset. That would ultimately just be replacing the offset you provided with one from your local time zone - and that would result in a completely different moment in time.

Perhaps you are just looking for a way to have a moment retain the time zone it was given? If so, then use the moment.parseZone function. For example:

var m = moment.parseZone("2012-12-31T00:00:00+0000");
var s = m.format();   // "2012-12-31T00:00:00+00:00"

You could also achieve this with moment.utc. The difference is that moment.parseZone will retain whatever offset you give it, while moment.utc will adjust to UTC if you give it a non-zero offset.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 3
    There is a really good reason you'd want to do this. Birthdays. Server sends User with property Birthday datetime set to midnight. The user does not care at ALL what time zone they are in or anything. It is easy to store all dates in your db in UTC and make webservers modify all outbound dates with UTC in ISO-8601. But it is very hard to do that AND modify a single property of an object to NOT add the timezone attribute to the value. – Bon Sep 30 '15 at 20:26
  • 1
    @klatzib - Sure, I can see that. I may have even done that before. :) But I'd consider it a hack to rely on client-side functionality to workaround a server-side issue. The only *correct* way to format a birthdate (or other calendar date) in ISO-8601 expanded form is `YYYY-MM-DD`, without time or offset. – Matt Johnson-Pint Sep 30 '15 at 20:31
  • Well darn, turns out in the time since last I read the docs, my ORM added support for simple Date datatypes instead of their prior support only for DateTime. I guess now there isn't really an excuse anymore. Drat. – Bon Sep 30 '15 at 21:00
  • Oh! Actually now I remember. I did check that out but it doesn't matter because I'm using .Net and it just handles the Date fields as DateTime objects with time set to 00:00:00 when deserialized. And my server conversion to UTC is for DateTime types, so there isn't a way around it really for people running .Net webservers except an additionally complicated pattern for per-property exceptions to the UTC conversion based on some attribute added to the property. – Bon Sep 30 '15 at 21:03
  • Except it seems DateTimeZoneHandling is an enum. Not a class that can be overridden... – Bon Sep 30 '15 at 21:05
  • 1
    @klatzib -Yes, it's tricky, but it is doable. You can set `DateTimeZoneHandling.RoundTripKind` and rely on `DateTimeKind` set correctly to `Unspecified` (for birthdays), but it will still show time at midnight. At least that will (mostly) work in moment.js properly. Unless, of course, if you're in Brazil and the date is on the DST spring-forward transition... You can always write a custom `JsonConverter`, or just use Noda Time with `LocalDate` objects.... but we're getting off topic from the OP here. Feel free to ask in a new question if needed. :) – Matt Johnson-Pint Sep 30 '15 at 21:56
  • @MattJohnson I am using the parseZone but somehow it pull my application performance a lot. Do you know what is the equivalent way to parse but in another library? – trungk18 Jan 17 '19 at 09:34
7

I know I'm late to the party, I had the same question and my searches didn't bring me any closer. I broke down and read the documentation and there is an option in moment for a String + Format:

String + Format docs

moment(String, String);

moment(String, String, String);

moment(String, String, Boolean);

moment(String, String, String, Boolean);

and more words, then this:

Unless you specify a time zone offset, parsing a string will create a date in the current time zone.

moment("2010-10-20 4:30",       "YYYY-MM-DD HH:mm");   // parsed as 4:30 local time
moment("2010-10-20 4:30 +0000", "YYYY-MM-DD HH:mm Z"); // parsed as 4:30 UTC

The part that gave me pause was the example that was used to parse local time omitted the +0000, which lead me to think the input string needed to have that removed, but it doesn't.

example:

var time = "2012-12-31T00:00:00+0000";
var x = moment(time); // Sun Dec 30 2012 19:00:00 GMT-0500
var y = moment(time,'YYYY-MM-DD'); //Mon Dec 31 2012 00:00:00 GMT-0500
vrtis
  • 712
  • 9
  • 9
4

You can ignore the browser's timezone completely by creating a new moment using moment.utc() instead of moment().

For example, if you are trying to work purely with a UTC date/time of the browser's current time but want to discard its timezone data, you can recreate the browser's current time into a UTC format using the following:

let nowWithTimezone = moment();
let nowInUtc = moment.utc(nowWithTimezone.format('MM/DD/YYYY HH:mm'), 'MM/DD/YYYY HH:mm');

Further documentation on moment.utc(): https://momentjs.com/docs/#/parsing/utc/

Steven
  • 3,526
  • 3
  • 18
  • 28
3

If you know for sure your input string is in the ISO-8601 format, you could just strip off the last 5 digits and use that in the Moment constructor.

var input = "2012-12-31T00:00:00+0000"
input = input.substring(0, input.length-5)
moment(input).toString()
> "Mon Dec 31 2012 00:00:00 GMT-0600"
khalid13
  • 2,767
  • 2
  • 30
  • 48
  • Yeah - that's pretty much what I came up with as well, but just not too happy about the solution. Would have thought that momentjs or moment-timezone had something in it that would do this without me having to resort to string manipulation. – Eric B. Aug 21 '14 at 21:01
1

There are valid reasons to do what the OP is asking for. The easiest way to do this with Moment is using its parseZone(date) method. No futzing around with string manipulation or multiple calls. It effectively parses the date string as though it were in the browser's local time zone.

pmont
  • 2,083
  • 22
  • 43
0

This is difficult task to do with MomentJS, it will basically depend as well on your current timezone.

Documentation as well is vague for this specific task, the way I solved the issue on my side was by adding hours to the date before converting it to JSON format.

var dt = moment("Sun Sep 13 2015 00:00:00 GMT-0400", "ddd MMM DD YYYY HH:mm:ss GMT-0400", false);
var date = dt.add(2, 'hour').toJSON();
console.log(date); //2015-09-13T00:00:00.000Z
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Thomas Modeneis
  • 687
  • 8
  • 11
0

Momentjs default logic will format the given time with local timezone. To format original date, I wrote a function:

https://github.com/moment/moment/issues/2788#issuecomment-321950638

frustigor
  • 392
  • 3
  • 8
0

Use moment.parseZone to convert without taking into account the timezone.

const moment = require('moment')

const dateStr = '2020-07-21T10:00:00-09'

const date = moment.parseZone(dateStr)

console.log(date.format('MM-DD-YY HH:mm A')) // 07-21-20 10:00 AM

Try here link to docs

Fawaz
  • 3,404
  • 3
  • 17
  • 22
-1

The best way is to use:

dt = moment("Wed Sep 16 2015 18:31:00 GMT-0400", "ddd MMM DD YYYY HH:mm:ss GMT-0400",true);

And to display convert again to desired timezone:

 dt.utcOffset("-04:00").toString()
 output > Wed Sep 16 2015 18:31:00 GMT-0400
Thomas Modeneis
  • 687
  • 8
  • 11