使用 StringFormat 将时间戳(长类型)从 XAML 转换为日期和时间

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

我有一个时间戳 属性,它是 long 类型,我已将它绑定到 ListView 列。 使用 XAML 我试图将此时间戳(long 类型)转换为日期和时间,具体取决于 运行.

机器的当前区域设置

我想要这样的东西:

mm/dd/yyyy HH:mmdd/mm/yyyy HH:mm(24 小时制)

mm/dd/yyyy hh:mm 下午或 dd/mm/yyyy hh:mm 下午(12 小时格式)

取决于机器区域设置。

所以我用StringFormat:

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

不过好像不行。在网格视图单元格中,它显示为 long 数字。

ggeneral format specifier,它将 long 显示为数字。

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.

日期格式化机制不能直接与 long 一起使用。 DateTime 表示日期和时间是明确的,但是您如何从哪里将 long 解释为秒、毫秒?请参阅 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.

显而易见的解决方案是通过 DateTime 类型的 属性 公开日期,而不是 long。然后您可以在 XAML StringFormat.

中使用标准和自定义日期格式说明符
public DateTime Timestamp { get; }

或者,您可以创建自定义值转换器,将 long 转换为 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();
   }
}

在范围内的任何资源中创建转换器实例,例如Window.Resources.

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

conversion happens before formatting以来,您可以保留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'}"/>

您可以参考Custom date and time format strings创建所需的格式字符串。

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

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

更新您的评论:

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

我假定了 Unix 时间戳。如您所见,long 非常不明确。在这种情况下,您可以将 long 转换回 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.

转换器方法正是这样做的。

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

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