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

Javascript Send Schedule Date From Local Timezone to Server Time

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

整个Angular申请date/times都是在PST参考中写的。

示例目标是将日期安排在 4:30PM PST

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

我们的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)。

打字稿class

export interface ScheduleDto { 
   scheduleDate?: Date;

scheduleDate: "2021-03-18T02:30:00.000Z"

C#class

public class ScheduleDto   
{
   public DateTime? ScheduleDate { get; set; }

....

return TimeZoneInfo.ConvertTime(ScheduleDate , TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"));

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

那么,您问题的最终答案是 - 是的,您使用 Moment-timezone 编写的代码确实会应用正确的偏移量。但是,它有点冗长。您实际上不需要做任何关于检测当前本地时区的事情。您可以改为只构建 Date 对象:

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

鉴于 Moment's project status,最好改用 Luxon(除非您已经在项目中广泛使用 Moment)。在 Luxon,那将是:

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

或者您可以使用 date-fns-tz 中的 zonedTimeToUtc 函数。

重点是,由于您正在构建一个 Date 对象,因此您总是通过网络发送它的一些字符串表示形式。您似乎正在使用 .toISOString() 序列化那些 Date 对象,这将发送 UTC 等价物 "2021-03-18T02:30:00.000Z"。获得正确的 UTC 时间点是最重要的。

在您的 .NET 代码中,如果您将该值接收到一个 DateTime 对象中,那么它的 Kind 属性 将被设置为 Utc,因为Z 在字符串的末尾。 TimeZoneInfo.ConvertTime 将使用 Kind 属性 来确定转换的源时区,并且您提供的目标时区为太平洋时间。

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

备选方案:

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

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