18

My application synchronises data across several different devices. For this reason it stores all dates in the UTC time-zone to account for different devices possibly being set to different time zones.

The trouble is that when I read the dates back out and display them they appear to be incorrect (most of the users are on British Summer Time so they're an hour behind).

<TextBlock Margin="5" Style="{StaticResource SmallTextblockStyle}">
    <Run Text="Last Updated:" />
    <Run Text="{Binding Path=Submitted}" />
</TextBlock>

Do I need to manually override set CurrentCulture property of the UI thread? I know I have to do this in Silverlight.

Askolein
  • 3,250
  • 3
  • 28
  • 40
BenCr
  • 5,991
  • 5
  • 44
  • 68

1 Answers1

21

Are you specifying "Utc" as DateTime.Kind when parsing the stored DateTime and also converting it to DateTime.ToLocalTime()?

public DateTime Submitted {
  get {
    DateTime utcTime = DateTime.SpecifyKind(DateTime.Parse(/*"Your Stored val from DB"*/), DateTimeKind.Utc);

    return utcTime.ToLocalTime();
  }

  set {
    ...
  }
}

^^ works fine for me

Update:

class UtcToLocalDateTimeConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
      return DateTime.SpecifyKind(DateTime.Parse(value.ToString()), DateTimeKind.Utc).ToLocalTime();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
      throw new NotImplementedException();
    }
  }

xaml:

<Window.Resources>
  <local:UtcToLocalDateTimeConverter x:Key="UtcToLocalDateTimeConverter" />
</Window.Resources>
...
<TextBlock Text="{Binding Submitted, Converter={StaticResource UtcToLocalDateTimeConverter}}" />
Viv
  • 17,170
  • 4
  • 51
  • 71
  • I'm not doing anything when loading the DateTime from the database, I'm just using EntityFramework ModelFirst entities as they come. Maybe I need to override that property. – BenCr Jun 04 '13 at 15:56
  • @BenCr well you could do the same I had in the property getter in a converter then. I'll edit my answer in a sec – Viv Jun 04 '13 at 15:58
  • 1
    No need, I can knock out a converter, I just didn't want to go down that path of adding it to every binding with a date in it. I was hoping that something in the XAML engine would format dates according to the current UI culture settings. – BenCr Jun 04 '13 at 16:02
  • @BenCr The problem is something somewhere will need to tell the system the `Kind`. AFAIK current culture can indicate the format such as "dd" before "mm" and such but not the actual DateTime kind itself. – Viv Jun 04 '13 at 16:09
  • I was thinking of using something like this to set the DateKind as I load objects out of the DB. It will obviously impact performance but I might be able to cache the properties for the types to alleviate that slightly. http://stackoverflow.com/a/11682982/396861 – BenCr Jun 04 '13 at 16:14
  • Now that I think of it though, only a fraction of the dates that I load will be displayed. It might be easier to add an additional read only computed property that does the conversion in the getter. That would remove the need for converters but would also add presentation logic into my model layer. – BenCr Jun 04 '13 at 16:16
  • @BenCr Yeh indeed, the chosen method widely differs in such cases and it's best to go with what your comfortable with or what you normally do in such cases elsewhere in your project. As long as you mention the Kind for the input DateTime, from an output POV doesn't really matter where. If your wanting this a "testable" area of your app, prefer to do it right near the source – Viv Jun 04 '13 at 16:19
  • I'd replace ```DateTime.Parse(value.ToString())``` at least to ```value is DateTime dt ? dt : DateTime.Parse(value.ToString())```, if it can be not only a ```DateTime```, and just to ```value``` otherwise. – N. Kudryavtsev Sep 03 '18 at 12:32