繁体   English   中英

.NET日期,Moment.js,UTC和时区转换

[英].NET date, Moment.js, UTC and Timezone shifting

我通过Ajax调用获得了UTC日期,例如"/Date(1517216466000+0100)/"
打印到控制台的时间是: Mon Jan 29 2018 10:01:06 GMT+0100 (W. Europe Standard Time)

我需要做的是让用户更改时区:我可以轻松地做到,例如moment(myDate).tz("Japan")

然后,我需要将日期保存为UTC格式,但无法执行。
我一直在尝试使用moment.utc() ,但是对于上面的输入,它返回的时间减少了1小时

如何处理这种情况? 综上所述:
1.从Web服务获取UTC时间
2.让用户更改时区
3.将修改后的日期保存在UTC中(不带时区)
工作演示: https : //stackblitz.com/edit/angular-kqrct7?file=app%2Fapp.component.html

编辑澄清:
让我们看一下时间。 我从WCF得到的日期是10点。 浏览器将其解释为GMT + 1中的10点,但是当我将其转换为UTC时,它变为9点。
我想这是10点为UTC。 然后,如果我修改了时区和该日期的分钟数,那么我希望能够获得该日期的UTC值。

EDIT2:简化了我的问题

  1. 我有一个UTC日期,该日期是从Web服务获得的,例如:“ / Date(1517216466000 + 0100)/”,它是:打印时,2018年1月29日星期一10:01:06 GMT + 0100(W.Europe Standard Time)进行控制台。

  2. 我在其中添加了带有moment(this.inputDate).tz(“ Europe / Berlin”)。format()的时区,但由于我的浏览器是GMT + 1,所以它仍然保持10:01:06。

  3. 我希望将原始字符串用作UTC日期,并且应该保持10:01:06,而不是09:01:06(如您在上面看到的(第二时刻示例)),所以时区为“ Europe / Berlin” 11:01:6

.NET JSON格式的日期 “ / Date(1517216466000 + 0100)/”中,可以忽略时区偏移量。 它表示“ 2018-01-29T09:01:06.000Z”,其中源系统的时区偏移为+0100。 因此,如果您不关心源时区,请忽略它。

这也是与格林威治标准时间+0100(W.欧洲标准时间)2018年1月29日星期一相同的时刻,只是偏移量不同。

UTC不是格式,而是时间标准。 如果要使用ISO 8601格式:

  1. 提取第一个数值
  2. 转换成数字
  3. 传递给Date构造函数
  4. 在产生的日期上调用toISOString方法

 var s = '/Date(-1517216466000+0100)/'; console.log(new Date(+s.replace(/^[^\\d-]+(-?\\d+).*$/,'$1')).toISOString()); 

您也可以使用moment.js对其进行解析和格式化,根据文档该文档可以处理.NET JSON格式,而无需指定格式。 因此,您可以执行此操作,也可以提取时间值并使用“ x”格式令牌对其进行解析:

 var s = '/Date(1517216466000+0100)/'; // Let moment.js guess the format console.log(moment(s).utc()); // Extract time value and supply format console.log(moment(s.replace(/^[^\\d-]+(-?\\d+).*$/,'$1'), 'x').utc()); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script> 

"/Date(1517216466000+0100)/"是序列化日期/时间的非标准方式。 看一下ISO8601 ,它定义了几种表示日期和时间的标准方法。

话虽这么说,让我们看看它被评估为...

moment("/Date(1517216466000+0100)/").toDate()

给我(英国) Mon Jan 29 2018 09:01:06 GMT+0000 (GMT Standard Time)

仅采用时间戳记值1517216466000

new Date(1517216466000)

还给出了Mon Jan 29 2018 09:01:06 GMT+0000 (GMT Standard Time)

这意味着+0100被忽略。

您实际上并没有在修改时间,那么为什么还要将其保存为除Mon Jan 29 2018 09:01:06以外的任何其他Mon Jan 29 2018 09:01:06

更新

但是“原始”字符串表示Mon Jan 29 2018 09:01:06 UTC +0100被忽略,这恰好是您对UTC的偏移量也是+0100 一关。

偏移量和时区是两个不同的东西。 时区包括UTC的偏移量以及夏令时的生效时间。 仅仅因为它说+0100不一定意味着(W. Europe Standard Time),所以它也很容易成为(西非时间)(West Africa Time),这也是UTC + 0100,但根本没有观察到夏令时。

您使用"/Date(1517216466000+0100)/"无法传达足够的信息来说出它是哪个时区,而JS / moment仅使用时间戳1517216466000 ,因此使用UTC。 当您使用console.log() ,浏览器会将其作为本地时间写到屏幕上Mon Jan 29 2018 10:01:06 GMT+0100 (W. Europe Standard Time)但这仅是基础日期Mon Jan 29 2018 10:01:06 GMT+0100 (W. Europe Standard Time)的表示。

通过告诉时刻使用特定时区,仅更改日期/时间的显示方式,而实际上并未更改其表示的时间。

如果使用日期选择器更改日期/时间,则必须以适当的方式序列化值以发送到后端,以便您无法更改的.Net应用能够理解并传达您的意图。

  1. 从服务器获取日期为var serverTime = "/Date(1517216466000+0100)/"
  2. 使用moment var time = new moment(serverTime)将其转换为JS Date
  3. 让用户指定TimeZone,即日本标准时间(UTC + 9) time = time.tz("Japan")
  4. time仍然代表Mon Jan 29 2018 09:01:06 UTC但是当在屏幕上显示time.format()时,其显示为"2018-01-29T18:01:06+09:00" time.format() "2018-01-29T18:01:06+09:00"

您说“我希望现在是世界标准时间10点”。 不幸的是,您的值不是 10点UTC,也不会是10点UTC,因为不是。 现在是世界标准时间9点

您可以自己解析从服务器获得的值,但是从服务器获取的时间 UTC 9am。 如果您将其更改为UTC上午10点,那么您会看到该时间为Mon Jan 29 2018 11:01:06 GMT+0100 (W. Europe Standard Time) -当地时间11点。

感谢大家的详细回答,他们对我的理解有很大帮助! 但是,正确的解决方案是:

数据库中的UTC时间是10时,在Moment.js中它被解释为UTC的9时,因为C#将其作为本地时间进行处理。 因此,在将日期发送给客户之前,我必须指出其UTC:

var utcToClient = DateTime.SpecifyKind(downtime.DownTimeStartUTC, DateTimeKind.Utc)

然后,在瞬间,我可以使用以下内容创建一个UTC:

var jsUtc = moment.utc(downtime.DownTimeStartUTC)

更改时区变得轻而易举:

jsUtc.tz(userSelectedTimezone)

并将日期保存在数据库中,我在C#中使用了它:

var utcFromClient = Record.DownTimeStartUTC.ToUniversalTime()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM