How to control appearance of ':' in time zone offset when parsing/formatting Datetime
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 runtime. I see that there is a formatting option "zzz" for including timezone informa开发者_开发技巧tion when parsing and formatting, however, it appears that the colon (:) is fixed. For instance, a Datetime formatted with the custom format string (yyyyMMddHHmmsszzz) might appear as:
20100309101530-05:00
The protocol I am working with does not include the colon in the timezone offset. This protocol will format datetimes, and expect them to be formatted as:
20100309101530-0500
Is there a way to control the appearance of the colon when parsing or formatting datetime with a custom formatter that includes the timezone offset?
Doesn't look like there is anything built-in (you can use zz
, but that leaves out the minutes).
You can roll your own by instantiating a DateTimeFormatInfo
, setting TimeSeparator
to string.Empty
and using that as the IFormatProvider
when calling DateTime.ToString
(and make the call explicit, if it is not already).
But frankly, using Replace
to remove the unwanted :
from the default return value is so much easier.
I faced the same problem, ended up using an extension
public static class DateTimeExtensions
{
public static String ToSomeFormat(this DateTimeOffset dateTime)
{
return dateTime.ToString("yyyyMMddHHmmsszzz").Replace(":", "");
}
}
If you're using it in a place where it doesn't make sense to use replace or extend (for example something that might want to output as -05:00
with a colon when passed as zzz
) and the minutes don't matter you could fake it with zz00
.
var date = new DateTimeOffset(2008, 8, 1, 0, 0, 0, new TimeSpan(-5, 0, 0));
Console.WriteLine(date.ToString("yyyy-MM-dd-HH:mm:ss(zz00)"));
// outputs 2008-08-01-00:00:00(-0500)
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 :
.
精彩评论