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
。
我在夏威夷。从 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
。