Home > front end >  Parsing DateTime with/without time zone information
Parsing DateTime with/without time zone information

Time:09-17

I am trying to implement the DICOM specification for parsing of DateTime. The standard specify that:

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.

So far all I could come up with is

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

I've successfully tested it with:

var dateTimeValueStr = "20010301125745.490000";

and

var dateTimeValueStr = "20010301125745";

However I cannot understand the documentation on how to implement parsing of the optional suffix for the offset from Coordinated Universal Time (UTC). It seems 'zzz' only works with an explicit colon sign ':'. And I cannot use something like "\\ hhmm", since there would be multiple 'h' pattern in the same format string.

Q:

Is there a way to read this DICOM DateTime with a single call to DateTime.ParseExact ? Or do I need a separate call to DateTime.ParseExact for reading the DateTime (no timezone) and then a second call to TimeSpan.ParseExact to parse the timezone info (see here).

Typical example:

var dateTimeValueStr = "20010301125745.490000-0500";

CodePudding user response:

You can try providing several formats in one DateTime.ParseExact:

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

Demo:

  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);

Outcome:

     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
  • Related