AM/PM 中午和午夜的指定特殊情况

AM/PM designatior special case for noon and midnight

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 表示上午,P 表示下午?

更新可能的解决方案:

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

I was aiming for something of a generic solution where the format could change like ddmm hhmmt or hmtt and the overload would take care of the various formats except for the special case of the "t" specifier.

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

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"