How to control appearance of ':' in time zone offset when parsing/formatting Datetime

前端 未结 4 1511
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-06 17:40

I\'m working with a protocol that may optionally include a time zone offset when specifying datetime information. My code is written in C# and we are using the 4.0 .NET run

4条回答
  •  旧时难觅i
    2020-12-06 18:14

    I had exact same issue, trying to format/parse time zone in the format like +0730.

    Formatting DateTime with zzz will always output time offset in hh:mm format. Initially I though that it should be possible to get custom format by overriding DateTimeFormatInfo.TimeSeparator (: by default), but in case of the time zone it's hardcoded in System.DateTimeFormat.FormatCustomizedTimeZone:

    // 'zzz*' or longer format e.g "-07:30"
    result.AppendFormat(CultureInfo.InvariantCulture, ":{0:00}", offset.Minutes);
    

    Here's response of engineer working on .NET:

    The zzz is formatted as a time span and not regular DateTime. It has been decided since day one to use the standard format for the formatting the time zone part in the date/time objects. So, it is intentional always using : as a separator for the formatting the time span part. I understand you can argue this not the correct decision, but we cannot change this now as the scope of breaking will be very big as many people depend on parsing the dates assuming this format. You can still workaround this issue by replacing : with the desired separator you want.

    So the here's my version of how to custom formatting of the timezone:

        var utcOffset = dateTime.Kind == DateTimeKind.Utc? TimeSpan.Zero : TimeZoneInfo.Local.GetUtcOffset(dateTime);
        var utcOffsetSrt = (utcOffset < TimeSpan.Zero ? "-" : "+") + utcOffset.ToString("hhmm", CultureInfo.InvariantCulture);
        var dateTimeStr = dateTime.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture);
        var result = dateTimeStr + utcOffsetSrt;
    

    Parsing however works out of the box with zzz for empty separator:

    var result = DateTime.ParseExact("+0000", "zzz", customInvariantCulture);
    var resultOffset = TimeZoneInfo.Utc.GetUtcOffset(result.ToUniversalTime());
    Assert.AreEqual(offset, resultOffset);
    

    Looking into System.DateTimeParse.ParseTimeZoneOffset:

    if (str.Match(":"))
    {
        // Found ':'
        if (!ParseDigits(ref str, 2, out minuteOffset))
        {
            return false;
        }
    }
    

    So zzz will work only if you have no delimiter or when it's :.

提交回复
热议问题