Javascript将计划日期从本地时区发送到服务器时间


我在夏威夷。从Angular,我想发送太平洋标准时间(PST(到C#Net核心API。它将把它保存在数据库中,并保存在太平洋标准时间。(我没有创建架构,只是注意到(。

整个Angular应用程序的日期/时间都是参考PST编写的。

示例目标是将日期安排在太平洋标准时间下午4:30

我们今天了解到一个错误,如果我们发送日期"2021-03-17T16:30:00",我们的应用程序会在夏威夷时区创建new Date("2021-03-17T16:30:00")。然后C#可能做了正确的事情,并将任何时间转换为太平洋本地时间(TimeZoneInfo.ConvertTime(dateTime, TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"))。因此,我们错误地转换为晚上7:30。

我们的API请求数据类型为日期。这个解决方案有效吗?然而,我觉得最后4行不会计入夏令时,或者可能会产生问题。

const inputDate = "2021-03-17T16:30:00";
const pstMoment = moment.tz(inputDate, 'America/Los_Angeles');
const clientTimeZoneName = Intl.DateTimeFormat().resolvedOptions().timeZone;
const clientMoment = pstMoment.clone().tz(clientTimeZoneName);
console.log(new Date(clientMoment.format())); // this will send to API
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.33/moment-timezone-with-data-10-year-range.js"></script>

注:代码解析不仅适用于夏威夷,也适用于可能没有夏令时的其他全球国家。我们的日程日期选择器使用字符串存储类型(inputDate(。

Typescript类

export interface ScheduleDto { 
scheduleDate?: Date;
scheduleDate: "2021-03-18T02:30:00.000Z"

C#类

public class ScheduleDto   
{
public DateTime? ScheduleDate { get; set; }
....
return TimeZoneInfo.ConvertTime(ScheduleDate , TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"));

如果我理解正确的话,问题是您当前在客户端上的方法只是创建一个类似new Date("2021-03-17T16:30:00")Date对象,它将使用本地时区来确定您所说的时间点。您希望它始终被解释为太平洋时间,但由于夏令时的原因,您不知道该使用哪个偏移量。

因此,你的问题的最终答案是——是的,你使用Moment时区编写的代码确实会应用正确的偏移量。不过,它有点冗长。您实际上不需要做任何与检测当前本地时区有关的事情。相反,您可以使用构建Date对象

moment.tz('2021-03-17T16:30:00', 'America/Los_Angeles').toDate()

考虑到Moment的项目状态,最好使用Luxon(除非您已经在项目中广泛使用Moment(。在卢森,这将是:

luxon.DateTime.fromISO('2021-03-17T16:30:00', {zone: 'America/Los_Angeles'}).toJSDate()

或者,您可以从日期fns-tz开始使用zonedTimeToUtc函数。

关键是,由于您正在构建一个Date对象,所以您总是通过连线发送它的一些字符串表示。您似乎正在用.toISOString()序列化这些Date对象,这将发送UTC等效的"2021-03-18T02:30:00.000Z"。使UTC时间点正确是最重要的。

在.NET代码中,如果将该值接收到DateTime对象中,则由于字符串末尾的Z,其Kind属性将设置为UtcTimeZoneInfo.ConvertTime将使用Kind属性来确定转换的源时区,并且您已将目标时区提供为太平洋时间。

更简单的方法是不要在客户端代码中使用Date对象,而是通过有线发送预期的日期和时间,而不使用偏移量"2021-03-17T16:30:00"。在.NET代码中,DateTime.Kind将是Unspecified。那么您根本不会调用TimeZoneInfo.ConvertTime,因为您已经在所需的时区中有了值。

替代方案:

对于TypeScript数据类型,可以使用字符串。

将来,当Temporal完成并完全集成到ECMAScript中时,可以使用PlainDateTime

最新更新