/ / DateTimeOffset parsowanie i niestandardowa strefa czasowa - c #, strefa czasowa, timezoneoffset, datetimeoffset

DateTimeOffset parsowanie i niestandardowa strefa czasowa - c #, strefa czasowa, timezoneoffset, datetimeoffset

Analizujemy wartości XML DateTime na wartość DateTimeOffset. Według Dokumentacja W3C XSD dla DateTime, typ może zawierać informacje o strefie czasowej lub nie.

Nasze wymaganie mówi:

  • Jeśli informacje o strefie czasowej są podane w formacie XML, użyj tej strefy czasowej
  • Jeśli nie podano informacji o strefie czasowej, załóż, że jest to czas lokalny we wstępnie zdefiniowanej, konfigurowalnej strefie czasowej (nie tej z serwera).

Problem polega na tym, że gdy XML DateTime bezstrefa czasowa jest analizowana w DateTimeOffset, domyślnie korzysta z lokalnej (systemowej) strefy czasowej. Wydaje się, że nie można przesłonić domyślnej strefy czasowej, a także nie można zidentyfikować, kiedy strefa czasowa została przeanalizowana lub dodana wewnętrznie.

Czy jest jakiś sposób, aby określić domyślną strefę czasową używaną podczas analizowania DateTimeOffset?
Jeśli nie, w jaki sposób można stwierdzić, czy strefa czasowa została przeanalizowana lub dodana automatycznie podczas analizowania DateTimeOffset?

Wydaje mi się dziwne, że nie ma wsparcia ustawiania strefy czasowej dla aplikacji .NET w taki sam sposób, jak można ustawić bieżącą kulturę.

Dlatego jedynym podejściem do tego problemu wydaje się najpierw parsowanie wartości na DateTime i sprawdzenie właściwości Kind. Jeśli rodzaj nie jest Nieokreślony, ponownie przeanalizuj wartość w DateTimeOffset:

/*
sample values:
- 2015-06-03T10:47:01
- 2015-06-03T07:47:01Z
- 2015-06-03T10:47:01+03:00
*/

DateTimeOffset dto;
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["DefaultTimeZone"]);
var dt = DateTime.Parse(value);

if (dt.Kind == DateTimeKind.Unspecified)
{
dto = new DateTimeOffset(dt, timeZone.GetUtcOffset(dt));
}
else
{
dto = DateTimeOffset.Parse(value);
}

Odpowiedzi:

2 dla odpowiedzi № 1

Najprostszym sposobem byłoby przetestowanie łańcucha przed czasem, aby sprawdzić, czy zawiera przesunięcie. Wyrażenia regularne działają do tego dobrze.

Oto funkcja, która powinna działać dobrze w opisanym przypadku:

static DateTimeOffset ParseAsDateTimeOffset(string s, TimeSpan defaultOffset)
{
if (Regex.IsMatch(s, @"(Z|[+-]d{2}:d{2})$"))
return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture);

var dt = DateTime.Parse(s, CultureInfo.InvariantCulture);
return new DateTimeOffset(dt, defaultOffset);
}

Możesz również rozważyć jego niewielką odmianę, która ma na celu zapewnienie wartości domyślnej strefa czasowa, zamiast domyślnego offsetowy. Jest to ważne rozróżnienie, ponieważ przesunięcie strefy czasowej może się zmieniać w zależności od tego, czy konkretna data przypada w okresie letnim, czy nie. Zobacz także „Strefa czasowa! = Przesunięcie” w wiki tagu strefy czasowej.

static DateTimeOffset ParseAsDateTimeOffset(string s, TimeZoneInfo defaultTimeZone)
{
if (Regex.IsMatch(s, @"(Z|[+-]d{2}:d{2})$"))
return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture);

var dt = DateTime.Parse(s, CultureInfo.InvariantCulture);
return new DateTimeOffset(dt, defaultTimeZone.GetUtcOffset(dt));
}