What Time Is It? Global Time (Steve Lasker)

What Time Is It? Global Time (Steve Lasker)

Rate This
  • Comments 8

You’re building apps that are hosted in the cloud. Your users can be anywhere across the globe. When you’re viewing a customer service call log, and you see a customer called at 4:30pm and was really upset their service was still down, how do you know how long ago they called? Was the time relevant to your time zone, the customers, or the person who took the call? Was it 5 minutes ago, or 3 hours and 5 minutes ago? Or was it the time zone of the server where the app is hosted? Where is the app hosted? Is it in your office on the west coast, the London office, or is the app hosted in Azure. If it’s in Azure, which data center is it located? Does it matter?

Some more questions, this time in the form of a riddle. Yes, time is a theme here.

    • What time never occurs?
    • What time happens twice a year?

What we’re dealing with here is a concept I call global time. At any given time, humans refer to time relevant to a given location. Although time is a constant, the way we refer to time is relative. 

There is a concept called UTC, in which time is relevant to the same location and would be a constant if the whole world would refer to 5:00pm as the same exact point in time no matter where you are. However, as humans we don’t think that way. We like 5:00pm represents the end of a typical work day. We like to know we all generally eat at 12:00 pm, regardless of where we are on the planet. However, when we have to think about customer call logs being created from multiple locations, at any time, it’s almost impossible to read a string of 4:30 pm, and know its true meaning in the global view of time.

What about time zones?

So we can all wake about the same time to a beautiful sunrise, we can all eat around noon, go out for drinks at sunset, or an 8:00 pm movie and it most likely be dark, time zones were created as chunks of consistent time as our planet rotates around it’s axis.

image

This seems to make things relatively easy, right? Everyone can refer to 9-5 as common work hours.

What about Daylight Savings Time

Time zones would have been fine if the earth were spinning consistently related to the sun. However, as we happen to spin around and around our own axis, we also spin around the sun.

clip_image002And, we spin at a slight enough angle that the sun doesn’t always rise at 6am within a given time zone. In 1916, daylight savings time was started where once a year we’d spring ahead, or fall back an hour to try and get the sun to rise and fall about the same time.
To make things a bit worse daylight savings time changed in 2007 when it was felt it would improve our energy consumption.
All of this was fine, when we lived in little towns, didn’t really connect with others across the globe instantly. Even in modern times, when apps were islands upon themselves on each of our “PCs”, possibly connected via floppynet, it wasn’t a problem. When the corporate office was located in Dallas, we all knew that time was relevant to Dallas time. But, in this new world, where there may no longer be a corporate office, or the data center may no longer be located in the basement of the corporate office, we need a better solution.

Problems, problems, but what to do?

In 2008, SQL Server 2008 and .NET Framework 3.5 SP1 introduced a new Date Time datatype called DateTimeOffset. This new type aims to balance the local time relevance humans seek, with the global time needs for our applications to function in a constant.
DateTimeOffset allows humans to view a date & time as we think about it locally, but it also stores the offset relative to UTC. This combination supports a constant, and allows apps to reason over time in their time zone.

An Example

Assume we’re located in the Redmond WA office. It’s 4:35 pm. According to our call log, our upset customer called at 4:30pm. If we store this without the offset, we have no idea how this relates to where we are right now. Did the NY, Redmond or London office take the call? If the user that saved the value was on the east coast, and it used their local time, it would store 4:30pm and -5 as the offset.
Using this combination of time and offset, we can now convert this to west coast time. The app pulls the time from the database. It calculates Pacific Time which is UTC -8, and subtracts another 3 hours (ET (UTC -8) – PT (UTC -5)). Our customer called at 1:30pm Pacific time. That’s 3 hours ago, and there’s no log of activity. Our customer is likely very upset. However, if it were stored as 4:30 pm – 8 (Pacific Time), the customer called just 5 minutes ago, and we can make sure someone from service is tending to their outage.

LightSwitch, Cloud Business Apps and Global Time

With a focus on cloud apps, Visual Studio 2013 LightSwitch and Cloud Business Apps now support the DateTimeOffset data type.

image

Apps can now attach to databases and OData sources that use DateTimeOffset, and you can now define new intrinsic databases with DateTimeOffset.

Location, Location, Location

When building apps, there are 3 categories of use for the DateTimeOffset data type:

  • Client Values
    Values set from the client, user entered, or set in javascript
     screen.GlobalTime.ClientValue = new Date();
  • Mid-Tier Values
    Set through application logic, within the LightSwitch server pipeline
     partial void GlobalTimes_Inserting(GlobalTime entity){
    entity.MidTierValue =
    DateTimeOffset.Now;
    }
  • Created/Modified Properties
    LightSwitch and Cloud Business Apps in Visual Studio 2013 now support stamping entity rows with Created/Modified properties. These values are set in the mid-tier.
    A future blog post will explain these features in more detail

Because the tiers of the application may likely be in different time zones, LightSwitch has slightly different behavior for how each category of values are set.

  • Client Values
    No surprise, the client values utilize the time zone, or more specifically the UTC Offset of the client. This obviously depends on the devices time, which can be changed, and does change on cell tethered devices as you travel across time zones.
  • Mid-Tier Values
    Code written against the mid-tier, such as the Entity Pipeline, uses the UTC Offset of the servers clock. This is where it gets a little interesting as the clock varies. In your development environment, using your local machine, it’s going to be your local time zone. For me, that’s Redmond WA UTC-8.  If you’re publishing to an on-premise server, your datacenter may likely use the local time zone as well. In our Dallas TX example, that would be UTC –6.  However, if you’re publishing to Azure, the servers are always in UTC-0 regardless of the data center. This way your apps will always behave consistently, regardless of where the servers are located.
  • Created/Modified Properties
    We considered making these use the Server time zone, but felt it would be better to be consistent regardless of where the server was located. This solves the problem for data that may span on-prem and the cloud. Created/Modified values are always UTC -0

A Quick Walkthrough

Using the above example, let’s look at how these values would be stored in the database, and viewed in the app from New York and Redmond WA

We’ll create a Entity/Table with the following schema:

image

Under the covers, LightSwitch will create a SQL Table with the following schema.

image

Just as noted above, we’ll create a screen, and enter values in the ClientValue on the Client, the MidTierValue on the MidTier, and LightSwitch will automatically set the Created property.

For the sake of simplicity, I normalized the values and removed the variable for how fast someone could type and press save on the client and have it be the exact time on the server. Reality often confuses a message.

Let’s assume its 1:30:30 PM on 9/19/2013, which is Daylight savings time in the pacific northwest. What values would be set for our 3 Properties?

    Stored As:   Displayed In The Browser In
Property   On Prem   Hosted In Azure   New York (EDT)   Redmond WA (PDT)
ClientValue 9/19/2013 1:30:30 PM -07:00 9/19/2013 1:30:30 PM -07:00 9/19/2013 4:30:30 PM 9/19/2013 1:30:30 PM
MidTierValue 9/19/2013 1:30:30 PM -07:00 9/19/2013 8:30:30 PM +00:00 9/19/2013 4:30:30 PM 9/19/2013 1:30:30 PM
Created 9/19/2013 8:30:30 PM +00:00 9/19/2013 8:30:30 PM +00:00 9/19/2013 4:30:30 PM 9/19/2013 1:30:30 PM

Notice the Created is always in UTC – 0. The mid tier uses the time of the server. And the browser client, displays all values consistently as the UTC Offset normalizes the times regardless of the time zone in which they were captured.

What date is it?

That wasn’t so bad, just a little math on the hour. However, let’s assume we’re working late that same night, and it’s now 10:30 PM on 9/19/2013 in Redmond WA. We’re still in daylight savings time, but what do you see different here?

    Stored As:   Displayed In The Browser In
Property   On Prem   Hosted In Azure   New York (EDT)   Redmond WA (PDT)
ClientValue 9/19/2013 10:30:00 PM -07:00 9/19/2013 10:30:00 PM -07:00 9/20/2013 1:30:00 AM 9/19/2013 10:30:00 PM
MidTierValue 9/19/2013 10:30:00 PM -07:00 9/20/2013 5:30:00 AM +00:00 9/20/2013 1:30:00 AM 9/19/2013 10:30:00 PM
Created 9/20/2013 5:30:00 AM +00:00 9/20/2013 5:30:00 AM +00:00 9/20/2013 1:30:00 AM 9/19/2013 10:30:00 PM

Although it’s 9/19 in Redmond, New York is 3 hours ahead. It’s now 1:30 AM 9/20. Also notice that our Azure servers are also working in 9/20.

Standing on the edge

It’s now the 2nd Sunday in March 2014. March 9 to be specific. This is the night before daylight savings time begins. Lets see what happens

  Stored As: Displayed In The Browser In
Property On Prem Hosted In Azure New York (EDT) Redmond WA (PDT)
ClientValue 3/9/2014 11:30:00 PM -07:00 3/9/2014 11:30:00 PM -07:00 9/20/2013 2:30:00 AM 9/19/2013 10:30:00 PM
MidTierValue 3/9/2014 11:30:00 PM -07:00 3/10/2014 7:30:00 AM +00:00 9/20/2013 2:30:00 AM 9/19/2013 10:30:00 PM
Created 3/10/2014 7:30:00 AM +00:00 3/10/2014 7:30:00 AM +00:00 9/20/2013 2:30:00 AM 9/19/2013 10:30:00 PM

In this case, not only are the times split across dates between New York and Redmond WA, but we’ve also crossed into daylight savings time. Instead of New York being 3 hours ahead, it’s actually 4 hours ahead, for the same point in time. Ouch…

My Head Hurts

Attempting to calculate all these different time zones, daylight savings time – if it even applies to your time zone, can certainly be confusing. So, what to do? Well, that of course depends. However, just as we learned in math, we need to find the least common denominator. In most cases, if you convert to UTC, you can avoid the variables. You can use TimeSpan to calculate the differences in two DateTime periods. Then, you can re-apply the UTC offset. However, none of this would be possible if the values you’re attempting to calculate didn’t include the UTC Offset.

Thus, LightSwitch, and Cloud Business Apps now support this important element for you to calculate Dates & Times across your globally deployed application.

What about the riddles?

Ahh, you’re still here?

    • What time never occurs?
      2:00 am on the 2nd Sunday of March
      As of 2007, the 2nd Sunday in March begins daylight savings time. At 2:00 am, the clocks will “leap” forward to 3:00 am skipping the 2:00 am hour all together
    • What time happens twice a year?
      1:00 am, the first Sunday of November
      As of 2007, the first Sunday in November ends daylight savings time. At 2:00 am, the clocks roll back to 1:00 am to end daylight savings time.

Some references

Thanks,
Steve Lasker
Program Manager, Visual Studio
http://blogs.msdn.com/SteveLasker

 

Leave a Comment
  • Please add 7 and 4 and type the answer here:
  • Post
  • Steve, interesting article highlighting the date/time issues when globalizing an app.

    My thoughts on the matter were that Lightswitch should  have been designed, at the outset, where all times were converted by the user (Lightswitch) control to UTC values regardless where the client was running the app, or located and thus UTC values passed on and saved in the server. This control should display these values as local time.  Good that the team has educated us all on how to extend LS.

    BTW the Daylight Saving switch-over would be handled by the client app (similar to the way Windows Clock is managed) and derived from the devices environment variables, as indeed is the norm. The riddles that you identify do not exist with UTC and, I feel, the addition of the Date Time Offset would, thus, be redundant, and perhaps a record of the client location may be more appropriate.

    For audit I see a What, Who, When and Where when (sic) it comes to globalization. Perhaps we're missing Why! :-)

    PS Still working with Lightswitch after all these years! Nice tool.

  • Hi +:-,

    Thanks for the comments.

    We did hope to add DateTimeOffset when we first shipped LightSwitch to avoid the migration problem. However, at the time, the underlying runtime we were using didn't support DateTimeOffset. What we have now with the DateTimeOffset feature is just what you're asking for. It will store the values as outlined in the blog, but will normalize to the users local time, based on their device of course.

    The normalization to the users local time does require the offset tho, as you point out in the riddle, not everyone follows daylight savings time. Just having some fun with DST, which as with most jokes, the context is important, and here in the states, we deal with this all the time, which doesn't apply to everyone. Just made a bit worse that [we] then moved when DST starts and stops. Like it wasn't confusing enough.

    The storage of the offset does map to the users local time, so I think we're getting at what you were looking for. It does take some time to digest, as the variables make it, well, fun.

    Steve

  • Thanks for a great explanation. While I did figure this out, it's great to then find a concise article that confirms it.

  • Possessive pronouns (it) do not have apostrophes. Please fix "around it’s axis" to "around its axis."

  • Isn't it just easier to save all Date/Time values in UTC, and convert them to local when manipulated on client?

  • Hi Chris,

    DateTimeOffset is essentially UTC, but it has the offset as well. The additional info allows you to know the timezone (well, not truly the timezone, but rather the offset as it doesn't account for daylight savings time) the data was set.  While you could store in UTC, it becomes an unwritten rule that people must know the value stored is UTC. While other datetime fields might be relative. For instance, stores open 9-5, regardless of UTC. A birthdate was at 8am, which I suppose could be stored as UTC as well. Probably important for those astrologer types.

    The main point is DateTimeOffset is explicit about the timezone, where DateTime isn't and it must be assumed.

    Hope that helps, and as always thanks for reading and providing feedback,

    Steve

  • It's great to see that DateTimeOffset solves some of the problems with DateTime (for example, DateTime always tacks a "Z" on the end for the "u" format string even when Kind == Local). I see that even DateTimeOffset.UtcNow.ToLocalTime().ToString("u") is truly Zulu time!

    But after all this time, I find that the most common ISO 8601 format includes both the separating "T" and "Z" for UTC combined date-times. Yet the "u" format string always omits the "T" which is allowed by ISO 8601, but not common in my experience. It's easy enough to solve (either with a custom format string or actually allocating a new string just to replace the space with "T"), but an optional format specifier (like "ut" or something) would be nice and not a breaking change. After all, DateTime and DateTimeOffset both correctly parse ISO 8601 strings with or without the "T", so why not allow printing either way natively from the Framework?

  • It is ironic, is it not, that the answer for your riddle is only correct for some of the world's time zones? Time to think globally! :)

    Great article. Thanks! (And one more thing; look up "Summer Time")

Page 1 of 1 (8 items)