我有一个包含员工信息的页面。所有数据中包括雇用日期。其定义如下:
export class Agent {
public HireDate: Date|any=null;
// other fields left out
}
在 HTML 中,我有以下内容:
<mat-form-field>
<mat-label>Hire Date</mat-label>
<input matInput [matDatepicker]="topicker" placeholder="Hire Date" [(ngModel)]="agent.HireDate" />
<mat-datepicker-toggle matSuffix [for]="topicker"></mat-datepicker-toggle>
<mat-datepicker #topicker></mat-datepicker>
</mat-form-field>
我从我自己的代码中获取了这个,其中有 from 和 to 日期,因此有
#topicker
的奇怪名称。当我必须创建一个简单的事件记录器时,我重用了更多自己的代码。因此我有:
export class Incident {
public Id: number;
public Occurrence: Date|any = null;
public Notes: string = '';
}
以及更熟悉的 HTML:
<mat-form-field>
<mat-label>Incident Date</mat-label>
<input matInput [matDatepicker]="topicker" placeholder="Incident Date"
[(ngModel)]="newIncident.Occurrence" />
<mat-datepicker-toggle matSuffix [for]="topicker"></mat-datepicker-toggle>
<mat-datepicker #topicker></mat-datepicker>
</mat-form-field>
他们的行为应该都是一样的,对吧?第一轮代码没问题。使用借用代码的第二轮很好。但最后一个失败了。我在这两种情况下都将网络数据追踪到 API,并在有效负载中看到了这一点:
HireDate: "2023-08-01T00:00:00"
哪个是正确的。但在该事件的有效负载中,我看到了这一点:
Occurrence: "2023-08-02T05:00:00.000Z"
这也可以说是正确的,但有所不同。不同之处在于使 .NET API 阻塞并将其视为 1-Jan-0001。我认为我可能搞砸了 POST 操作,但我尝试将内容转储到控制台,并且在 POST 操作之前看到了差异。
console.log( this.agent );
...
HireDate: "2023-08-01T00:00:00"
这与管道中流出的内容相匹配。但记录另一个告诉我一些其他的事情:
console.log( this.newIncident );
...
Occurrence: > Wed Aug 02 2023 00:00:00 GMT-0500 (Central Daylight Time) {}
(> 是控制台窗口中的小三角形。)我知道日期的字符串表示形式和日期本身之间可能存在差异。我已经尝试了所有我能想到的方法来说服两个几乎相同的代码保持相同的行为,但到目前为止还没有成功。
这是怎么回事?我该如何解决?
我怀疑第二个日期是您通过
new Date()
创建的,但不是第一个? JavaScript 中的原生日期并不直观(概述“陷阱”的示例文章:https://dev.to/zachgoll/a-complete-guide-to-javascript-dates-and-why-your-date-is- off-by-1-day-fi1),当您创建 Date
实例时,您是根据客户端(即用户)计算机的本地时间来创建它。
通常建议使用诸如
date-fns
(https://date-fns.org/) 之类的库。从历史上看,moment.js
是最受欢迎的,但是该项目现在处于“维护模式”,并且由于其工作方式而被认为有些遗留。这里提到的其他替代方案:https://blog.openreplay.com/dealing-with-dates-and-times--alternatives-to-momentjs/。这些库将允许您更好地控制日期,最值得注意的是能够创建日期而不必担心用户的本地时间/时区是什么。
序列化的
Z
日期后缀的 Occurrence
表示时间部分是 UTC(Z 表示祖鲁时间,大致相同),即 0
偏移量。
虽然有时需要将“本地”时间与日期一起使用,即如果用户指定某件事发生的确切时刻,而不仅仅是日期;当您想要午夜日期(即时间部分不相关)时,您希望使用 UTC 进行用户输入、显示和存储。显示非 UTC 格式的“永恒”日期将导致“负偏移”时区(例如 PST、EST 等)显示错误的日期。为此,主要步骤之一是您希望 Moment 日期选择器使用 UTC - 您可以通过
useUtc
上的 MAT_MOMENT_ADAPTER_DATE_OPTIONS
来完成此操作,请参阅 https://material.angular.io/components/datepicker/overview .
在较高层面上,您的下一步应该是:
DateTime
对象采用 UTC。date-fns
等库(Material 现在也支持此功能)。特别是当您创建日期时,因为您希望将其创建为 UTC,而不是用户的系统时间。不这样做可能意味着: