解析 DateTime with/without 时区信息

Parsing DateTime with/without time zone information

我正在尝试实现用于解析 DateTime 的 DICOM 规范。标准 specify 即:

A concatenated date-time character string in the format:

YYYYMMDDHHMMSS.FFFFFF&ZZXX

The components of this string, from left to right, are YYYY = Year, MM = Month, DD = Day, HH = Hour (range "00" - "23"), MM = Minute (range "00" - "59"), SS = Second (range "00" - "60").

FFFFFF = Fractional Second contains a fractional part of a second as small as 1 millionth of a second (range "000000" - "999999").

&ZZXX is an optional suffix for offset from Coordinated Universal Time (UTC), where & = "+" or "-", and ZZ = Hours and XX = Minutes of offset.

到目前为止我能想到的就是

DateTime.ParseExact(str, "yyyyMMddHHmmss.FFFFFF", CultureInfo.InvariantCulture);

我已经成功测试了它:

var dateTimeValueStr = "20010301125745.490000";

var dateTimeValueStr = "20010301125745";

但是我无法理解有关如何实现对协调世界时 (UTC) 偏移量的可选后缀的解析的文档。 'zzz' 似乎只适用于明确的冒号“:”。而且我不能使用像 "\+hhmm" 这样的东西,因为在相同的格式字符串中会有多个 'h' 模式。

问:

有没有办法通过一次调用 DateTime.ParseExact 来读取这个 DICOM 日期时间?或者我需要单独调用 DateTime.ParseExact 来读取日期时间(无时区),然后再调用 TimeSpan.ParseExact 来解析时区信息 ().

典型例子:

var dateTimeValueStr = "20010301125745.490000-0500";

您可以尝试提供 多种格式 合而为一 DateTime.ParseExact:

  static DateTime MyParse(string value) => DateTime.ParseExact(
    value, 
    new string[] { 
      "yyyyMMddHHmmss.FFFFFF", 
      "yyyyMMddHHmmss.FFFFFFzzz",
    },
    CultureInfo.InvariantCulture, 
    DateTimeStyles.AdjustToUniversal);

演示:

  string[] tests = new string[] {
    "20010301125745.490000",
    "20010301125745.490000-0500",
    "20010301125745.490000+0000",
    "20010301125745.490000-0000",
    "20010301125745.490000+0700",
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,30} => {MyParse(test):yyyy-MM-dd HH:mm:ss}"));

  Console.Write(report);

结果:

     20010301125745.490000 => 2001-03-01 12:57:45
20010301125745.490000-0500 => 2001-03-01 17:57:45
20010301125745.490000+0000 => 2001-03-01 12:57:45
20010301125745.490000-0000 => 2001-03-01 12:57:45
20010301125745.490000+0700 => 2001-03-01 05:57:45