不同时区的同一日期

38

我想知道如何获取不同时区的当天日期、月份、年份、小时数、分钟数和秒数,比如:

var now = moment().valueOf();
var result1 = moment(now).format('DD-MM-YYYY HH:mm:SS Z');
在我的时区,我会得到类似这样的东西:
18-02-2015 21:08:34 +01:00

我如何仅更改时区而不更改其他值(天、月、...、分、...)?

我想要获得像这样的东西:

    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

提前致谢


不确定您的意思。如果您更改了时区偏移量而没有调整时间,则它将不再代表同一时刻的“现在”。 - Matt Johnson-Pint
顺便说一下,你的代码中“now”是多余的。你可以删掉第一行,直接使用moment().format... - Matt Johnson-Pint
谢谢Matt,我的问题是在不改变任何内容(日期、月份、小时、分钟等),只改变时区的情况下获取相同的日期。这就是我需要的,但我无法实现。 - Zouhair
1
这在我看来是一个完全合理的用例。我的网站仅为特定时区设置预约,因此当用户从不同地点进行预约时,会得到不同的结果。 - catch22
4个回答

62

这里是你如何可能做你所问的事情:

// 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"

然而,你必须要认识到两件重要的事情:

  • another对象不再代表当前时间 - 即使在目标时区中。它是一个完全不同的时间点。(世界上并没有同步本地钟表,如果有的话,我们就不需要使用时区了!)

    因此,尽管上述代码满足了问题的要求,我强烈建议不要使用它。相反,重新评估你的需求,可能是你们误解了时间和时区的本质。

  • 一个时区无法仅通过偏移量来完全表示。请阅读时区标签维基页中的 "时区 != 偏移量"。虽然一些时区具有固定的偏移量(例如印度使用的+05:30),但许多时区在一年中的不同时间更改它们的偏移量,以适应夏令时

  • 如果你想考虑这一点,你可以使用moment-timezone,而不是调用utcOffset(...)。然而,我第一条的问题仍然存在。

// 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"

2
@Zouhair可能想要处理无用的库。以ngx-bootstrap的DatePicker为例,它总是处理本地时区,但如果您希望它在UTC上运行,则可以尝试使用以下代码来实现。 - HankCa
@MattJohnson,我希望在我的代码中更改时间。当我要求库使用GMT时,它返回本地时区的时间。因此,虽然我有一个代表美国东部标准时间上午8点的对象,但我想要一个代表格林威治标准时间上午8点的对象。 - Troy Daniels
没错,这是一个合理的使用情况。此外,我更新了答案以显示内置的解决方法(通过传递true参数)。不确定它是在哪个版本中添加的,但现在已经存在 - 因此无需手动减去偏移量。 - Matt Johnson-Pint
1
@drenda - 它仍然存在。对我来说是可以工作的。也许你有一个旧版本。或者你只安装了moment而没有安装moment-timezone插件。 - Matt Johnson-Pint
1
NuGet包已过期。如果您通过NuGet获取moment-timezone,则当前版本为v0.5.13。keepTime标志直到v0.5.14才被引入。 - user1676558
显示剩余5条评论

12

我认为最被投票的答案有点混乱。这里是一个更干净的解决方案 - 类似于BlueSam的答案,但更安全:

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

2
这与我所做的完全相同。 - Akhorus

7

阅读了以上评论后,我想根据Joao的回答进行补充。在我的情况下,我试图使用一个带有时区的现有moment日期,并将其转换为另一个时区,同时保留原始日期值(与问题中所要求的相同)。

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);

2

从文档开始:http://momentjs.com/timezone/docs/

引用 moment-timezone-with-data.js 并指定要前往的时区,如下所示:

moment(date).tz("America/Los_Angeles").format()

已更新。您可以在不包含时区的情况下格式化日期。 - BlueSam
2
你的代码有问题。你只需要调用moment().tz(“America / Los_Angeles”).format(“…任何格式…”)。按照你现在的写法,当字符串被格式化和重新解析时,可能会搞混月份和日期。(但是这仍然没有回答问题本身。) - Matt Johnson-Pint
1
我只是想举个例子。我已经更新了我的答案,以更准确地反映我想说的话。 - BlueSam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接