Home > Mobile >  Convert timestamp (long type) into date and time from XAML using StringFormat
Convert timestamp (long type) into date and time from XAML using StringFormat

Time:03-25

I have a timestamp property which is a long type and I have bound it to a ListView column. Using XAML I am trying to convert this timestamp (long type) into a date and time dependent on the current regional settings of the machine on which is running.

I would like to get someting like this:

mm/dd/yyyy HH:mm or dd/mm/yyyy HH:mm (24 hour format)

or

mm/dd/yyyy hh:mm PM or dd/mm/yyyy hh:mm PM (12 hour format)

depending on the machine regional settings.

So I use StringFormat:

<GridViewColumn Header="Id"
                DisplayMemberBinding="{Binding Path=Timestamp, StringFormat='g'}"/>

But it seems it is not working. In the grid view cell it is shown as a long number.

CodePudding user response:

The g is the general format specifier, which will display the long as number.

The general ("G") format specifier converts a number to the more compact of either fixed-point or scientific notation, depending on the type of the number and whether a precision specifier is present.

The date formatting mechanism does not work directly with long. A DateTime is unambiguous for representing a date and time, but how do you interpret long, as seconds, as milliseconds, from where? See the documentation for Standard date and time format strings.

A standard date and time format string uses a single character as the format specifier to define the text representation of a DateTime or a DateTimeOffset value.

The obvious solution is to expose the dates through a property of type DateTime, not long. Then you can use the standard and custom date format specifiers in XAML StringFormat.

public DateTime Timestamp { get; }

Alternatively, you can create a custom value converter that converts the long to a DateTime.

public class LongToDateConverter : IValueConverter
{
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      if (!(value is long milliseconds))
         return value;

      var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
      return dateTime.AddMilliseconds(milliseconds).ToLocalTime();

      // Alternative in > .NET Core 2.1
      //return DateTime.UnixEpoch.AddMilliseconds(milliseconds);
   }

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

Create an instance of the converter in any resources in scope, e.g. Window.Resources.

<Window.Resources>
   <local:LongToDateConverter x:Key="LongToDateConverter"/>
</Window.Resources>

Since the conversion happens before formatting, you can keep the StringFormat.

If you set the Converter and StringFormat properties, the converter is applied to the data value first, and then the StringFormatis applied.

<GridViewColumn Header="Id"
                DisplayMemberBinding="{Binding Path=Timestamp, Converter={StaticResource LongToDateConverter}, StringFormat='g'}"/>

You can refer to Custom date and time format strings to create the desired format string.

StringFormat='MM/dd/yyyy HH:mm'
StringFormat='dd/MM/yyyy HH:mm'

StringFormat='MM/dd/yyyy hh:mm'
StringFormat='dd/MM/yyyy'

Update for your comment:

I forgot to say in my post (sorry) that this long timestamp was obtained by doing DateTime.UtcNow.ToFileTimeUtc() [...]

I assumed the Unix timestamp. As you can see, a long is pretty ambiguous. In this case you can convert the long back as stated in the documentation.

The ToFileTimeUtc() method is sometimes used to convert a local time to UTC, and subsequently to restore it by calling the FromFileTimeUtc(Int64) method followed by the ToLocalTime() method. However, if the original time represents an invalid time in the local time zone, the two local time values will not be equal.

The converter method would do exactly this.

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
   if (!(value is long milliseconds))
      return value;

   return DateTime.FromFileTimeUtc(milliseconds).ToLocalTime();
}
  • Related