Kendo UI 调度程序错误地转换时间,向后加减小时

Kendo UI Scheduler incorrectly converting times, adding and subtracting hours backwards

我正在使用 Kendo 调度程序,时区偏移似乎在与应该发生的相反的方向上增加和减少小时数。

当我将客户端时区更改为更西部的时区时,事件日期时间会增加小时数,而当我将客户端浏览器更改为更东部的时区时,小时数会被减去。

因此太平洋时区的客户端应该看到开始时间为 10:00 上午,但它显示为 4:00PM。设置为大西洋时区的客户端将开始时间视为 12:00PM。

调度程序代码:

$("#scheduler").kendoScheduler({
    date: new Date(),
    height: 900,
    editable: false,
    views: [
        {
            type: "month",
            selected: true,
            eventHeight: 50,
            eventTemplate: $("#event-template-month").html(),
        },{
            type: "agenda",
            eventHeight: 50,
            eventTemplate: $("#event-template-sched").html(),
        }
    ],
    timezone: "America/New_York",
    dataSource: webinarSchedule,
});

事件信息保存在本地 js 文件的数组中,如下所示:

var webinarSchedule = [//Date are in utc -5:00
{
    title: "Part 1 <br/>The Golden Rule",
    shortName: "1) The Golden Rule ",
    presenter: "Bill Preston",
    description: "A great event",
    synopsis: "Learn stuff",
    seriesNote: "The first of a 4-part series.",
    registration: "https://attendee.gotowebinar.com/register/3782113333237861889",
    start: new Date("2015/1/24 1:00 PM"),
    end: new Date("2015/1/24 1:20 PM"),

},

是的,这似乎不对。

我发现在处理 JS 日期(或一般计算中的日期)时保持理智的唯一方法是使用 UTC 日期,以 ISO 格式序列化(通常,将 UTC 日期存储在服务器上也是一种更好的主意)。因此,我建议使用适用于源时区的 ISO 字符串创建您的事件:

{
    title: "Part 1 <br/>The Golden Rule",
    shortName: "1) The Golden Rule ",
    presenter: "Bill Preston",
    description: "A great event",
    synopsis: "Learn stuff",
    seriesNote: "The first of a 4-part series.",
    registration: "https://attendee.gotowebinar.com/register/3782113333237861889",
    start: new Date(Date.parse("2015-02-11T13:00:00-05:00")), 
    end: new Date(Date.parse("2015-02-11T13:20:00-05:00")),
}

然后根本不设置调度程序时区选项(因此它使用本地)。如果您需要传递给服务器,您可能还想先使用 toISOString 处理日期。

Scheduler 预计只接收和发送 UTC 日期 - 这就是为什么你应该使用 UTC 时区以正确的格式加载它的数据(否则当从字符串创建日期时,将使用本地用户时区,这是 JavaScript 具体行为):

start: new Date("2015-01-24T13:00:00.000Z"),
end: new Date("2015-01-24T13:20:00.000Z"),

此外,您可以将调度程序时区设置为 "Etc/UTC" - 这样,上述日期将按原样显示,无需在客户端进行转换:

$("#scheduler").kendoScheduler({
   date: new Date("2015/1/24"),
   timezone: "Etc/UTC",

这是一个基于上面代码片段的 JSFiddle:http://jsfiddle.net/loanburger/0s3Lcq17/

节目有点晚了,但我目前正在评估 Telerik 的 MVC 组件,并且在使用调度程序时遇到了类似的问题。我处理它的方式是让时区成为必需的,然后在服务器端我做了以下事情:

public SchedulerViewModel HandleTimezonesToUTC(SchedulerViewModel e)
{
    TimeZoneInfoHelper tziHelper = new TimeZoneInfoHelper();
    if (!string.IsNullOrEmpty(e.StartTimezone) && string.IsNullOrEmpty(e.EndTimezone))
    {
        TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(tziHelper.FindMSEquilivalent(e.StartTimezone));
        e.Start = DateTime.SpecifyKind(e.Start, DateTimeKind.Unspecified);
        e.End = DateTime.SpecifyKind(e.End, DateTimeKind.Unspecified);
        e.Start = TimeZoneInfo.ConvertTimeToUtc(e.Start, tzi);
        e.End = TimeZoneInfo.ConvertTimeToUtc(e.End, tzi);
    }
    if (!string.IsNullOrEmpty(e.StartTimezone) && !string.IsNullOrEmpty(e.EndTimezone))
    {
        TimeZoneInfo tziStart = TimeZoneInfo.FindSystemTimeZoneById(tziHelper.FindMSEquilivalent(e.StartTimezone));
        TimeZoneInfo tziEnd = TimeZoneInfo.FindSystemTimeZoneById(tziHelper.FindMSEquilivalent(e.EndTimezone));
        e.Start = TimeZoneInfo.ConvertTimeToUtc(e.Start, tziStart);
        e.End = TimeZoneInfo.ConvertTimeToUtc(e.End, tziEnd);
    }
    return e;
}

public SchedulerViewModel HandleTimezonesFromUTC(SchedulerViewModel e)
{
    TimeZoneInfoHelper tziHelper = new TimeZoneInfoHelper();
    if (!string.IsNullOrEmpty(e.StartTimezone) && string.IsNullOrEmpty(e.EndTimezone))
    {
        TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(tziHelper.FindMSEquilivalent(e.StartTimezone));
        e.Start = DateTime.SpecifyKind(e.Start, DateTimeKind.Utc);
        e.End = DateTime.SpecifyKind(e.End, DateTimeKind.Utc);
        e.Start = TimeZoneInfo.ConvertTimeFromUtc(e.Start, tzi);
        e.End = TimeZoneInfo.ConvertTimeFromUtc(e.End, tzi);
    }
    if (!string.IsNullOrEmpty(e.StartTimezone) && !string.IsNullOrEmpty(e.EndTimezone))
    {
        TimeZoneInfo tziStart = TimeZoneInfo.FindSystemTimeZoneById(tziHelper.FindMSEquilivalent(e.StartTimezone));
        TimeZoneInfo tziEnd = TimeZoneInfo.FindSystemTimeZoneById(tziHelper.FindMSEquilivalent(e.EndTimezone));
        e.Start = TimeZoneInfo.ConvertTimeFromUtc(e.Start, tziStart);
        e.End = TimeZoneInfo.ConvertTimeFromUtc(e.End, tziEnd);
    }
    return e;
}

通过这种方式,您将删除任何意外的 local->utc 转换,并且正如其他发帖人之一所说,让浏览器为您调整回当地时间。

理论上您不需要 fromUTC,但当我测试时,日历并未将其转换为本地时区。您可能只需分配一个 "kind" 即可,但我没有对此进行测试。

不确定您在做什么,但希望它能帮助您解决一些摇摆不定的时间问题。

我使用 moment.js

解决了这个问题

Javascript:

new Date(moment.utc("INSERT DATE HERE").format())

这样我就消除了时区问题。我不会更改 MVC 控制器上的日期。