question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Discussion: Formalizing approach to storing date and time values

See original GitHub issue

Current Situation

AllReady stores campaign/event/task dates as the .NET DateTimeOffset type

  • DateTimeOffset is a .NET Framework type that represents a particular point in time relative to UTC. It is a Date and Time with an Offset relative to UTC. (https://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx)
  • Each Campaign has a Windows/.NET TimeZoneID specifying the timezone where the campaign is located. For example, a campaign in Seattle would have the TimeZoneID = “Pacific Standard Time”
  • An Event within a campaign also has a TimeZoneID specifying the timezone where the event is located. The default TimeZoneID is the same as the campaign but can differ when events are located across the country.
  • All Tasks for an event inherit the TimeZoneID from the event.
  • A Campaign / Event / Task start and end date / time is stored as a DateTimeOffset with the offset set to the UTC offset according to the TimeZoneID of the campaign.
  • For example, consider the following campaign located in Seattle
Event Start Date Time with Offset End Date Time with Offset
Event 1 10/23/2016 5:00 PM -7:00 10/23/2016 8:00 PM -7:00
Event 2 12/20/2016 5:00 PM -8:00 12/20/2016 8:00 PM -8:00
  • Note the offset is different depending of whether or not the date and time falls during daylight savings time for the Seattle area. AllReady calculates this offset whenever date/time values are saved by calling TimeZoneInfo.GetUtcOffset for date/time that was specified by the user.
  • //TODO: Add example here of how and why the offset if adjusted when values are saved

Potential Risks Thank you to Jon Skeet for pointing out the following potential problems

  • Since the offset for a particular DateTimeOffset is calculated and stored when a user creates (or modifies) a Campaign / Event / Task, there is the potential that changes to time zone rules could cause problems. As an example, if an event were scheduled several months in advance and changes to the daylight savings time rules for that timezone changed after the event was created, the offset for that event might not be stored correctly.
  • AllReady uses Windows timezones which are updated via regular Windows Updates. These updates happen regularly but updates are typically not as timely as the IANA timezone database which is used by the Noda Time framework
  • Both these issues could be resolved if we used the Noda time framework, stored values as local date time values and did time zone conversions on every read. // TODO: Add example if we decide this is the path forward
  • Noda Time framework currently does not support .NET Core. Version 2.0 of Noda Time does support .NET core but it is currently in Alpha. It is considered stable but we should expect some API changes.

Display Campaign / Event / Task date time values

  • The default behavior in AllReady is to display Campaign / Event / Task dates in the timezone where the campaign is located. Since the values are stored as a DateTimeOffset, this means we simply display the value using .ToString(). No additional timezone adjustments are necessary.
  • To avoid confusing, we display the TimeZone after any date/time values as shown here: image
  • Optionally, a user can specify their local TimeZone in their user profile. If a user has specified their local timezone, we also display the Campaign / Event / Task datetimes in their local timezone as shown here: image
    • TODO: // Add example code showing how this conversion happens

Date Time formats

  • AllReady currenlty only supports the en-US culture, meaning that DateTime values are always displayed in MM/dd/yyyy format. This includes the input fields where users enter DateTime values. From Startup.cs
 // Configure the HTTP request pipeline.
var usCultureInfo = new CultureInfo("en-US");
app.UseRequestLocalization(new RequestLocalizationOptions
{
     SupportedCultures = new List<CultureInfo>(new[] { usCultureInfo }),
     SupportedUICultures = new List<CultureInfo>(new[] { usCultureInfo })
});
  • This can be extended in the future by adding more supported cultures at startup. The challenge here however is in aligning ASP.NET’s request culture (and associated DateTime format) with the momentjs DateTime format used by the eonasdan-bootstrap-datetimepicker UI component for datetime input fields.
  • Currently, the datetimepicker is setup to display in the ‘L’ format for Dates and ‘L LT’ formats for DateTime. Since we don’t include any additional momentjs locales, this forces the DateTime pictures to use the MM/dd/yyyy format.
 $(".datepicker").datetimepicker({
    format: 'L',
    showClose: false,
    toolbarPlacement: 'bottom'
});

$(".datetimepicker").datetimepicker({
    format: 'L LT',
    showClose: false,
    sideBySide: true,
   toolbarPlacement: 'bottom'
});

Issue Analytics

  • State:open
  • Created 7 years ago
  • Comments:13 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
stevejgordoncommented, Oct 31, 2016

Looks good @dpaquette. What’s really handy is that what you’ve done regarding binding pretty much matches what I’ve job for a work requirement I had and have started writing up for my blog. So at least my approach looks good for that too!

2reactions
dpaquettecommented, Oct 31, 2016

See PR #1416 for current WIP related to this issue. I am proposing a approach that uses a custom model binder to do the adjustment for the Campaign or Event’s timezone. This pulls the logic out of the controllers / command handlers and ensures the date time offsets are set correctly BEFORE they ever reach the controller.

I will be adding some documentation and unit tests later this week but wanted to share what I had working so far.

Read more comments on GitHub >

github_iconTop Results From Across the Web

database design - Preferred way to store DateTime
A common way of storing date/time data, employed "behind the scenes" by many products, is by converting it into a decimal value where...
Read more >
sql - Efficient way of storing date ranges
It is the best method if you have a lot of product codes in the Products table and few validity ranges for each...
Read more >
Date and Time Formats
Abstract. This document defines a profile of ISO 8601, the International Standard for the representation of dates and times. ISO 8601 describes ...
Read more >
Database: Should We Store Datetime or Timestamp?
Datetime and timestamp are both used to store date and time information ... date and time values in UTC format is usually the...
Read more >
Working With Dates & Times in Your Application
Learn how to work with dates and times when developing applications, including addressing bugs, accounting for time zones and more.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found