【问题标题】:AM/PM designatior special case for noon and midnight中午和午夜的 AM/PM 指定特殊情况
【发布时间】:2015-10-25 22:54:51
【问题描述】:

VB2012:我正在从旧系统读取数据。其中一个字段是时间,我正在将其读入 DateTime 变量。我使用“hhmmt”格式通过 DateTime.ParseExact 解析出日期。我遇到的唯一问题是遗留系统显示 A 表示 AM,P 表示 PM,而 N 表示中午的特殊情况。嗯 .NET 不喜欢 N 指示符,所以我检测到它并将其更改为 P。效果很好。

003 0300 AAABBB  845A 1200N
005 1400 CCCDDD 1055A  240P
007 7000 EEEFFF  306P  531P

现在我进行一些处理并将数据打印到文件中。我想以旧系统中打印的格式打印出时间。我的第一个想法是使用自定义 DateTimeFormatInfo

Dim info As New DateTimeFormatInfo
info.PMDesignator = "N"

并将其作为 IFormatProvider 提供给我的字符串格式化程序

trip.ArriveTime.ToString("hmmt", info)

但我意识到设置 DateTimeFormatInfo 是静态的,当时间是 12:00P 或中午时将没有任何用处。有没有办法创建一种格式来解决这种独特的情况,并在中午使用 N 后缀,但在其他时间保持标准 A 表示 AM,P 表示 PM?

更新可能的解决方案:

Imports System.Text.RegularExpressions
Imports System.Globalization

Module mdlExtensions
    Private rgxTimePeriod As New Regex("t+")
    <System.Runtime.CompilerServices.Extension()> _
    Public Function LegacyFormat(dt As DateTime, fmt As String, Optional provider As IFormatProvider = Nothing) As String
        Dim formatted As String
        If dt.TimeOfDay = New TimeSpan(12, 0, 0) Then
            fmt = rgxTimePeriod.Replace(fmt, "N")
        End If
        If provider Is Nothing Then
            formatted = dt.ToString(fmt)
        Else
            formatted = dt.ToString(fmt, provider)
        End If

        Return formatted
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToLegacy(dt As DateTime, fmt As String, Optional provider As IFormatProvider = Nothing) As String
        'setup the master DateTimeFormatInfo
        Dim ci As CultureInfo = CType(provider, CultureInfo)
        Dim mstrDtfi As DateTimeFormatInfo
        If provider Is Nothing Then
            'designate a new DateTimeFormatInfo class if Nothing was passed in
            mstrDtfi = New DateTimeFormatInfo
        Else
            'get a reference to the DateTimeFormatInfo class of the FormatProvider that was passed in
            mstrDtfi = ci.DateTimeFormat
        End If

        'check to see if the time is noon and set a new PMDesignator if it is
        If dt.TimeOfDay = New TimeSpan(12, 0, 0) Then
            mstrDtfi.PMDesignator = "NN"
        End If

        'check to see if the time is midnight and set a new AMDesignator if it is
        If dt.TimeOfDay = New TimeSpan(0, 0, 0) Then
            mstrDtfi.AMDesignator = "MM"
        End If

        'now format the date string with the proper provider 
        Dim formattedDate As String
        If provider Is Nothing Then
            formattedDate = dt.ToString(fmt, mstrDtfi)
        Else
            formattedDate = dt.ToString(fmt, ci)
        End If

        Return formattedDate
    End Function

End Module

【问题讨论】:

  • 您在尝试利用现有的格式化工具时想多了。 IFormatProvider 的问题在于它指定了一个 GetFormat 函数,该函数将 Type 作为参数。它对要格式化的值一无所知。只需编写您自己的函数,该函数将 DateTime 结构作为参数。如果您希望它内联,请将其编写为扩展方法。
  • 是的,我可能想多了。我的目标是一种通用的解决方案,其中格式可以像 ddmm hhmmt 或 hmtt 一样改变,并且重载会处理各种格式,除了“t”说明符的特殊情况。
  • 而不是使用 N(oon)/M(idnite) 指示符(1 毫秒后,它是 PM 或 AM);不要使用 1200 - 您可以添加一分钟,以便显示明确(1201 PM/AM)。
  • 不能这样做。时间必须准确地打印在旧系统中。

标签: vb.net datetime time datetimeformatinfo


【解决方案1】:

我的目标是一种通用的解决方案,其中格式可以像 ddmm hhmmt 或 hmtt 一样改变,并且重载会处理各种格式,除了“t”说明符的特殊情况。

一个简单的函数仍然可以处理这个问题。这是一个作为扩展方法的示例。

Module Extensions
    Private rgxTimePeriod As New Regex("t+")
    <System.Runtime.CompilerServices.Extension()> _
    Public Function LegacyFmt(dt As DateTime, fmt As String, Optional provider As IFormatProvider = Nothing) As String
        Dim formatted As String
        If dt.TimeOfDay = New TimeSpan(12, 0, 0) Then
            fmt = rgxTimePeriod.Replace(fmt, "N")
        End If
        If provider Is Nothing Then
            formatted = dt.ToString(fmt)
        Else
            formatted = dt.ToString(fmt, provider)
        End If
        Return formatted
    End Function
End Module

?#12:00#.LegacyFmt("hmmt", Globalization.CultureInfo.InvariantCulture)
"1200N"
?now.LegacyFmt("ddmm")
"2551"
?#2:01#.LegacyFmt("hmmt")
?#12:00#.LegacyFmt("hmtt")
"120N"
"201A"
?#2:01#.LegacyFmt("hmtt")
"21AM"

【讨论】:

  • 让我看看这个函数并了解它的部分,然后我会写回更新。
  • 好的,我想我知道你的扩展方法要去哪里了。在原始帖子中,我使用 DateTimeFormatInfo 类添加了您的解决方案以及我自己的解决方案之一。让我知道这个是否在正确的轨道上。
猜你喜欢
  • 1970-01-01
  • 2016-01-13
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 2012-10-22
  • 2011-10-14
  • 1970-01-01
相关资源
最近更新 更多