“相同”代码产生不同的日期字符串

问题描述 投票:0回答:1

我有一个包含员工信息的页面。所有数据中包括雇用日期。其定义如下:

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>

我从我自己的代码中获取了这个,其中有 fromto 日期,因此有

#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) {}

(> 是控制台窗口中的小三角形。)我知道日期的字符串表示形式和日期本身之间可能存在差异。我已经尝试了所有我能想到的方法来说服两个几乎相同的代码保持相同的行为,但到目前为止还没有成功。

这是怎么回事?我该如何解决?

angular date timezone picker
1个回答
0
投票

我怀疑第二个日期是您通过

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 .

在较高层面上,您的下一步应该是:

  • 确保您的日期输入配置为使用 UTC(在您的情况下,Moment 将允许通过配置进行此操作)。
  • 确保您的 API 期望您的
    DateTime
    对象采用 UTC。
  • 在任何地方显示日期时,请确保其显示为 UTC,而不是本地时间。
  • 在 JavaScript 中处理日期时,请使用
    date-fns
    等库(Material 现在也支持此功能)。特别是当您创建日期时,因为您希望将其创建为 UTC,而不是用户的系统时间。

不这样做可能意味着:

  • 用户输入的日期不正确且不可靠(可能会根据用户的时区而有所不同)
  • 向用户显示错误的日期(这通常表现为,例如,北美用户看到的日期比预期早)
© www.soinside.com 2019 - 2024. All rights reserved.