38

My question is how can I get the same day, month, year, hour, minutes, seconds in a different time zone, for example:

var now = moment().valueOf();
var result1 = moment(now).format('DD-MM-YYYY HH:mm:SS Z');

In my time zone I get some this like this:

18-02-2015 21:08:34 +01:00

So how can I change only time zone without changing other values (days, months, ..., minutes, ...)

I want to get some thing like this:

    result2: 18-02-2015 21:08:34 +01:00
    result3: 18-02-2015 21:08:34 +10:00
    result4: 18-02-2015 21:08:34 +05:00
    result5: 18-02-2015 21:08:34 -06:00
    result6: 18-02-2015 21:08:34 -11:00

Thanks in advance

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Zouhair
  • 611
  • 2
  • 8
  • 15
  • Not sure what you mean. If you changed the time zone offset without adjusting the time - then it would no longer represent the same "now" moment in time. – Matt Johnson-Pint Feb 19 '15 at 05:22
  • BTW - "now" is redundant in your code. You could just drop the first line and do `moment().format...` – Matt Johnson-Pint Feb 19 '15 at 05:22
  • thank you Matt, my problem is get the same date in defirent time zone, without changing nothing(days, month, hours, minutes, ...) only changing the time zone, that what i need, but i can´t get it. – Zouhair Feb 19 '15 at 08:35
  • 1
    This is a totally legit use case imo. I have a site that only sets appts for a specific timezone so when users made appts from a different location it was getting different results. – catch22 May 11 '18 at 19:34

4 Answers4

62

Here's how you could do what you are asking:

// get a moment representing the current time
var now = moment();

// create a new moment based on the original one
var another = now.clone();

// change the offset of the new moment - passing true to keep the local time
another.utcOffset('+05:30', true);

// log the output
console.log(now.format());      // "2016-01-15T11:58:07-08:00"
console.log(another.format());  // "2016-01-15T11:58:07+05:30"

However, you must recognize two important things:

  • The another object no longer represents the current time - even in the target time zone. It's a completely different moment in time. (The world does not synchronize local clocks. If it did, we'd have no need for time zones!).

    For this reason, even though the above code satisfies the question that was asked, I strongly recommend against using it. Instead, re-evaluate your requirements, as it's likely they are misunderstanding the nature of time and time zones.

  • A time zone cannot be fully represented by an offset alone. Read "Time Zone != Offset" in the timezone tag wiki. While some time zones have fixed offsets (such as +05:30 used by India), many time zones change their offsets at different points throughout the year to accommodate daylight saving time.

  • If you wanted to account for this, you could use moment-timezone instead of calling utcOffset(...). However, the issue in my first bullet would still apply.

// get a moment representing the current time
var now = moment();

// create a new moment based on the original one
var another = now.clone();

// change the time zone of the new moment - passing true to keep the local time
another.tz('America/New_York', true); // or whatever time zone you desire

// log the output
console.log(now.format());      // "2016-01-15T11:58:07-08:00"
console.log(another.format());  // "2016-01-15T11:58:07-05:00"
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Hi Matt thanks for the solution listed above it really works, but I am not sure how i can use moment.tz instead of offset can you elaborate how it would replace the example above? – Piotr Stulinski Jan 15 '16 at 17:22
  • I already did explain it. You simply replace the third line of code with the one I showed at the end. – Matt Johnson-Pint Jan 15 '16 at 19:24
  • I've expanded the answer to include the entire code, so you can see that the third line has been replaced, but it is still necessary to include the fourth line to shift the time by the difference in offsets. Again - this is code that satisfies the requirements, but is a clear indication of bad requirements and is not recommended. Push back on this one. – Matt Johnson-Pint Jan 15 '16 at 20:00
  • 2
    @Zouhair probably wanted that to deal with feckless libraries. Take `ngx-bootstrap`s DatePicker. It always deal with the local timezone but if you want it to be at UTC say, then something like this may work to make this happen. – HankCa May 17 '17 at 06:10
  • @MattJohnson I *want* to change the moment in my case. I have a library which, when I ask it to use GMT, returns moments in the local time zone. So while I have an object represent 8:00 EST, I want an object representing 8:00 GMT. – Troy Daniels Feb 02 '18 at 19:23
  • Yep, that's a reasonable use case. Also, I updated the answer to show the built-in way to address this (by passing the `true` parameter). Not sure exactly which versions that was added in, but it is there now - so no need to subtract the offsets manually. – Matt Johnson-Pint Feb 02 '18 at 21:09
  • @MattJohnson Seems that another.tz('America/New_York', true); is not a valid method. Is that removed in current version of momentjs? – drenda Mar 06 '18 at 13:07
  • 1
    @drenda - It's still there. Works for me anyway. Maybe you have an older version. Or maybe you have only moment and haven't installed the moment-timezone addon. – Matt Johnson-Pint Mar 06 '18 at 18:26
  • 1
    The NuGet package is out of date. If you're getting moment-timezone through NuGet, it's currently on v0.5.13. The keepTime flag wasn't introduced until v0.5.14. – user1676558 Aug 08 '18 at 16:46
  • Adding to @user1676558 comment, here is the link to the release 1.5.14 changelog: https://github.com/moment/moment-timezone/releases/tag/0.5.14 – Guillermo Gutiérrez Oct 01 '19 at 22:34
12

The most-voted answer is messy IMO. Here's a cleaner solution - similar to BlueSam's answer, but safer:

const myTime = moment.tz('2016-08-30T22:00:00', moment.ISO_8601, 'America/Denver')

myTime.format() //2016-08-30T22:00:00-06:00

const sameTimeDifferentZone = moment.tz(myTime.format('YYYY-MM-DDTHH:mm:ss.SSS'), moment.ISO_8601, 'America/New_York')

sameTimeDifferentZone.format() //2016-08-30T22:00:00-04:00
Joao
  • 2,696
  • 2
  • 25
  • 35
7

After reading the above comments, I thought I'd add in based on Joao's answer. In my case I was trying to use a preexisting moment date with a timezone and converting it to another timezone while retaining the original date value (as asked in the question).

var newTimezone = 'America/Denver';

//date - contains existing moment with timezone i.e 'America/New_York'
moment.tz(date.format('YYYY-MM-DDTHH:mm:ss'), 'YYYY-MM-DDTHH:mm:ss', newTimezone);
Stefan Savu
  • 91
  • 1
  • 1
2

From the moment docs: http://momentjs.com/timezone/docs/

reference moment-timezone-with-data.js and specify which timezone to go to, like so:

moment(date).tz("America/Los_Angeles").format()
BlueSam
  • 1,888
  • 10
  • 17
  • Updated. You could format the date without the timezone – BlueSam Feb 18 '15 at 21:30
  • 2
    Your code is off. You would just call `moment().tz("America/Los_Angeles").format("...whatever format...")`. The way you have it written will potentially mix up the month and day when the string is formatted and re-parsed. (But still, doesn't address the question the way it was asked.) – Matt Johnson-Pint Feb 19 '15 at 05:25
  • 1
    I was just trying to give an example. I've updated my answer to more accurately reflect what I was trying to say – BlueSam Feb 19 '15 at 05:31