Recurring event is wrong after it crosses day light savings

11 posts, 0 answers
  1. Logan
    Logan avatar
    61 posts
    Member since:
    Apr 2013

    Posted 17 Oct 2019 Link to this post

    My scheduler is having a problem when a user creates a recurring event that crosses a time change (day light savings).  If i create a recurring event for Oct 29 at 12PM and have it recur for 10 days it is correctly displayed at 12PM until Nov 3rd (after the time change) it starts showing at 11AM.

     

    The database record looks like 

    https://imgur.com/3zI3u2j

    The timezone is set to:.Timezone( "America/New_York")

    The other thing I notice is when i go in to edit an event in the Scheduler it shows in UTC time in the editor instead of in America/New_York.  Most of my events are not edited through the Scheduler UI, so this has not become a problem.

     

     
  2. Ivan Danchev
    Admin
    Ivan Danchev avatar
    2105 posts

    Posted 21 Oct 2019 Link to this post

    Hello Logan,

    Could you please post you Scheduler declaration? This will give us an idea of how it is configured and we will further investigate the reported behavior.

    Regards,
    Ivan Danchev
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  3. Logan
    Logan avatar
    61 posts
    Member since:
    Apr 2013

    Posted 22 Oct 2019 in reply to Ivan Danchev Link to this post

    I have removed some of the logic.
    @(Html.Kendo().Scheduler<ISchedulerEvent>()
        .Name("scheduler")
        .Date(startDate)
        .Height(600)
        .Views(views =>
        {
            views.DayView(w => w.Selected(false));
            views.WeekView(w => w.Selected(true));
            views.MonthView(w => w.Selected(false));
        })
        .Editable(e =>
        {
            e.Create(true);
            e.Update(true);
            e.Destroy(true);
        })
        .Timezone("America/New_York")
        .AllDaySlot(false)
        .CurrentTimeMarker(true)
        .EventTemplateId("display-template")
        .Events(events =>
        {
            events.Add("scheduler_add");
            events.Resize("scheduler_resize");
            events.ResizeEnd("scheduler_resizeEnd");
            events.Move("scheduler_move");
            events.MoveEnd("scheduler_moveEnd");
            events.Remove("scheduler_remove");
            events.Edit("scheduler_edit");
            events.DataBound("scheduleBound");
            events.Change("scheduler_removenever");
     
        }
    )
    .Resources(resource =>
    {
     
    resource.Add(m => m.CalendarItemAttendees)
    .Title("Technologist")
    .DataTextField("Text")
    .DataValueField("Value")
    .DataColorField("Color")
    .BindTo(Model.AllAttendees).Multiple(Model.RequiredSkills.Count > 1);
     
    resource.Add(m => m.HardwareId)
    .Title("Equipment")
    .DataTextField("Text")
    .DataValueField("Value")
    .DataColorField("Color")
    .BindTo(Model.AllAttendees).Multiple(Model.RequiredSkills.Count > 1);
     
    resource.Add(m => m.MeetingTypeId)
    .Title("Meeting Type")
    .DataTextField("Text")
    .DataValueField("Value")
    .DataColorField("Color")
    .BindTo(Model.AllMeetingTypes).Multiple(false);
    })
    .DataSource(d => d
    .ServerOperation(true) //this forces a re-read on change
    .Model(m =>
    {
    m.Id(f => f.Id);
    m.Field(f => f.Title).DefaultValue(Model.CalendarTitle);
    m.RecurrenceId(f => f.RecurrenceId);
    })
    .Events(e => e.Error("error_handler").RequestEnd("rebindSchedule")) //show user any errors
    .Read(r => r.Action("Schedule_Read", "Calendar").Data("calendarRead"))
    .Create("Schedule_Create", "Calendar")
    .Destroy("Schedule_Destroy", "Calendar")
    .Update("Schedule_Update", "Calendar")
    )
    )
  4. Ivan Danchev
    Admin
    Ivan Danchev avatar
    2105 posts

    Posted 24 Oct 2019 Link to this post

    Logan,

    I tried reproducing the reported behavior, but to no avail. The November 3rd event is shown properly: see the attached screenshot.

    A sample runnable project is attached to this reply. Could you run it and let me know whether there is any difference in how the recurring event is displayed at your end?

    Regards,
    Ivan Danchev
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  5. Logan
    Logan avatar
    61 posts
    Member since:
    Apr 2013

    Posted 28 Oct 2019 Link to this post

    I stripped everything out i could and I am still having the problem when i match my original setup, which was to set the timezone in the database to Etc/UTC and the timezone in the view to America/New_York.  My goal is to store it in the database as UTC, but for it to always be displayed in America/New_York time in the browser (even if their computer is set to something different).

    When I change the .TimeZone setting in the view to "Etc/UTC" it appears to be stay the same across daylight savings, but the time is incorrect.  It comes across as 12PM UTC but shows at 4PM.  This confuses me because my local timezone is America/New_York so i would think if it was being converted from UTC to EST it would be 8/7AM depending on daylight savings.

    You can see the output and data at https://imgur.com/a/g3Gc4MY 

    My test code is

    View

    @{
        ViewBag.Title = "Index";
    }
     
    <h2>Index</h2>
     
    @(
        Html.Kendo().Scheduler<Radiology.Web.Controllers.SchedulerEvent>()
        .Name("scheduler-test")
        .Date(DateTime.Today)
        .Height(300)
        .Views(v =>
        {
            v.DayView();
            v.WorkWeekView();
            v.WeekView(wv => wv.Selected(true));
            v.MonthView();
        })
        .Timezone("America/New_York")
        .DataSource(d => d
                        .ServerOperation(true) //this forces a re-read on change
                        .Model(m =>
                        {
                            m.Id(f => f.Id);
                            m.Field(f => f.Title).DefaultValue("no title");
                            m.RecurrenceId(f => f.RecurrenceId);
                    })
                    .Events(e => e.Error("error_handler")) //show user any errors
                    .Read(r => r.Action("Schedule_Read", "TestCalendar"))
                    .Create("Schedule_Create", "TestCalendar")
                    .Destroy("Schedule_Destroy", "TestCalendar")
                    .Update("Schedule_Update", "TestCalendar")
                    )
     
    )

     

    Classes

        public class SchedulerEvent : ISchedulerEvent
        {
            public int Id { get; set; }
            public string Title { get; set; }
            public string Description { get; set; }
            public bool IsAllDay { get; set; }
            public DateTime Start { get; set; }
            public DateTime End { get; set; }
            public string StartTimezone { get; set; }
            public string EndTimezone { get; set; }
            public string RecurrenceRule { get; set; }
            public string RecurrenceException { get; set; }
            public int? RecurrenceId { get; set; }
        }
     
        public class TestCalendarController : BaseController
        {
            // GET: TestCalendar
            public ActionResult Index()
            {
                return View();
            }
     
            public virtual async Task<JsonResult> Schedule_Read([DataSourceRequest] DataSourceRequest request)
            {
                var result = new DataSourceResult();
     
     
                var list = Db.CalendarItems
                    .Where(w => w.HardwareId == 21 && w.Id == 2337 && w.DeletedOn == null)
                    .Select(s => new SchedulerEvent()
                    {
                        Id = s.Id,
                        Title = s.Title,
                        Description = s.Description,
                        Start = s.Start,
                        StartTimezone = s.StartTimezone,
                        End = s.End,
                        EndTimezone = s.EndTimezone,
                        IsAllDay = false,
                        RecurrenceException = s.RecurrenceException,
                        RecurrenceRule = s.RecurrenceRule,
                        RecurrenceId = s.RecurrenceId
                    }).ToList();
     
                result = list.ToDataSourceResult(request, ModelState);
     
                var jsonResult = Json(result);
                jsonResult.MaxJsonLength = int.MaxValue;
     
                return jsonResult;
            }
        }
    }

     

    Thanks!

    Logan

     

     

     

     

     

     

  6. Logan
    Logan avatar
    61 posts
    Member since:
    Apr 2013

    Posted 28 Oct 2019 in reply to Logan Link to this post

    use this link the other had an htmlspace at the end for some reason https://imgur.com/a/g3Gc4MY
     
  7. Ivan Danchev
    Admin
    Ivan Danchev avatar
    2105 posts

    Posted 30 Oct 2019 Link to this post

    Hello Logan,

    The Start and End dates in the response in the screenshot miss the "Z" literal, which is part of the standard for UTC times. For example:

    "Start":"2013-06-09T21:00:00Z"

    Try out out the approach we demonstrate in the service used in out demos in your Schedule_Read action:

    Start = DateTime.SpecifyKind(s.Start, DateTimeKind.Utc),
    End = DateTime.SpecifyKind(s.End, DateTimeKind.Utc),

    See the Timezones article for more information on the Date format the Scheduler expects.

    Regards,
    Ivan Danchev
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  8. Logan
    Logan avatar
    61 posts
    Member since:
    Apr 2013

    Posted 04 Nov 2019 in reply to Ivan Danchev Link to this post

    Thanks for responding.

    I have added the following code directly after the database call in my sample above.

    list.ForEach(e =>
    {
        e.Start = DateTime.SpecifyKind(e.Start, DateTimeKind.Utc);
        e.End = DateTime.SpecifyKind(e.End, DateTimeKind.Utc);
    });

     

    This did add a "Z" to the end of the Start and End values when it is set to the browser, but i still have the same problem.  You can see this in the screenshots linked below

    https://imgur.com/a/Uw7nkzG

     

    Thanks for helping with this

     

     

  9. Ivan Danchev
    Admin
    Ivan Danchev avatar
    2105 posts

    Posted 06 Nov 2019 Link to this post

    Logan,

    I tested some more and made a change to the way dates are returned in the Read action in the project I attached earlier. Previously the date were being returned in this format: "Start":"\/Date(1572364800000)\/".

    I modified the Read action:

    public JsonResult Read([DataSourceRequest] DataSourceRequest request)
    {
        var events = from a in appointments
                     select new
                     {
                         TaskID = a.TaskID,
                         Description = a.Description,
                         Title = a.Title,
                         Start = a.Start.ToString("o"),
                         End = a.End.ToString("o"),
                         RecurrenceRule = a.RecurrenceRule
                     };
    
        return Json(events.ToDataSourceResult(request));
    }

    so now the dates are returned in this format: "Start":"2019-10-29T12:00:00.0000000Z"

    The event starting at 12PM UTC is shown starting at 8AM with the "America/New_York" timezone set.

    I am attaching the example again. Could you check how it behaves at your end? Are you able to reproduce the issue?

    Regards,
    Ivan Danchev
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  10. Logan
    Logan avatar
    61 posts
    Member since:
    Apr 2013

    Posted 06 Nov 2019 in reply to Ivan Danchev Link to this post

    Ivan,

    tl;dr: Removing the TimeZone fields from the read along with the trailing Z appears to have fixed it.  Is that right?

    Your sample did work on my machine, but it would be real work for me to match it in my production code because my model comes from a service and implements ISchedulerEvent which defines Start and End as DateTime.  I also saw that my code was not returning a json datetime.

    I noticed you were not setting the Start/EndTimeZone property on the read.  I has always set that value to Etc/UTC to specify the timezone.  When I removed this value from the read it appears to work in my sample.  

    Removing that value only appears to work when the Start/End times have the trailing Z to indicate time (otherwise they display on the calendar in UTC).

    I am going to move on to test this in the full system, but I wanted to make sure that this is a reasonable outcome and that it is OK to leave the StartTimeZone and EndTimeZone null in the scheduler read?

    Thanks again!

  11. Ivan Danchev
    Admin
    Ivan Danchev avatar
    2105 posts

    Posted 07 Nov 2019 Link to this post

    Logan,

    I am glad it worked out. Actually, I was not able to reproduce the problematic behavior even with Start/EndTimeZone set to "Etc/UTC". But these two fields are not obligatory. Passing dates with the Z literal specify them as UTC dates and then the Scheduler's Тimezone option is applied.

    Regards,
    Ivan Danchev
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Back to Top