Как определить, что сейчас британское летнее время

У меня есть следующий код, который должен возвращать смещение 60 (чтобы показать, что в настоящее время в Великобритании мы находимся по британскому летнему времени, т. е. на 60 минут раньше GMT):

var info = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
double off = localServerTime.Offset.TotalMinutes;
return off;

Однако он возвращает 0.

Может ли кто-нибудь помочь исправить это для меня?


person Mark    schedule 22.10.2014    source источник
comment
Вы нигде не использовали info. Таким образом, ваш off будет смещением текущего часового пояса.   -  person Soner Gönül    schedule 22.10.2014
comment
@ vc74 Вопрос вводит в заблуждение. Переменная info инициализируется, но в остальном не используется. Возвращаемое смещение основано только на DateTimeOffset.Now.   -  person    schedule 22.10.2014
comment
Интересно. Это отлично работает для меня (чешское летнее время). Вы уверены, что ваш сервер настроен правильно, с правильным часовым поясом?   -  person Luaan    schedule 22.10.2014
comment
@vc74 UTC == GMT, всегда. Вы, кажется, говорите, что Британия в настоящее время находится в GMT (или UTC), а не в BST, но я не верю, что это правильно, и Википедия согласна со мной, что BST не заканчивается до следующих выходных.   -  person    schedule 22.10.2014
comment
BST не заканчивается до воскресенья, и DateTimeOffset.Now.Offset.TotalMinutes возвращает 60 для меня в Великобритании прямо сейчас.   -  person Ben Robinson    schedule 22.10.2014
comment
@hvd Вы правы, поэтому в этом случае сервер должен быть настроен по Гринвичу.   -  person vc 74    schedule 22.10.2014


Ответы (4)


Используйте метод TimeZoneInfo.IsDaylightSavingTime (DateTimeOffset). чтобы узнать, переводится ли сейчас летнее время для вашего часового пояса.

var info = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
bool isDaylightSaving = info.IsDaylightSavingTime(localServerTime);

Дополнительные примеры можно найти здесь

person Adrian Sanguineti    schedule 22.10.2014
comment
Использование стандартного часового пояса по Гринвичу не сработало для меня, поскольку оно, по-видимому, не поддерживает переход на летнее время. Вместо этого мне пришлось использовать стандартное время по Гринвичу. - person Zhorian; 20.04.2018

Ваша машина настроена неправильно, если вы получили 0 и живете в Великобритании. Вероятные причины:

  • Часовой пояс устройства установлен неправильно. Нажмите на часы на панели задач, чтобы исправить.
  • Машина не настроена на соблюдение летнего времени. Нажмите на часы.
  • База данных, которую TimeZoneInfo использует для определения правил перехода на летнее время, устарела или повреждена. Он хранится в разделе реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.

Будьте осторожны при внесении радикальных изменений, поскольку неправильная настройка вполне могла быть сделана намеренно, чтобы обойти какой-то недостаток в критически важном для бизнеса приложении, которое работает на сервере. Сначала поговорите с тем, кто администрирует сервер.

person Hans Passant    schedule 22.10.2014

Другой вариант — использовать Noda Time.

Следующий код работает с Noda Time 1.4 и выше:

var zone = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default.ForId("Europe/London");
var zonedClock = NodaTime.SystemClock.Instance.InZone(zone);
var zonedDateTime = zonedClock.GetCurrentZonedDateTime();
bool isDST = zonedDateTime.IsDaylightSavingTime();
Console.WriteLine(isDST);
  • zone – это объект DateTimeZone, представляющий часовой пояс Великобритании, "Европа/Лондон". "
  • zonedClock — это объект ZonedClock, который в данном случае представляет систему часы и часовой пояс Великобритании
  • zonedDateTime — это объект ZonedDateTime, представляющий текущую дату и время в часовом поясе. («текущий момент, предоставленный базовыми часами, с поправкой на часовой пояс этого объекта»)
  • isDST — это логическое значение, указывающее, находится ли текущий момент в DST или нет. На момент написания (апрель 2018 г.) это оценивается как true.

В более ранних версиях Noda, где ZonedClock недоступен, вместо этого мы можем сделать это:

var zone = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default.ForId("Europe/London");
var now = Instant.FromDateTimeOffset(DateTimeOffset.Now);
var zonedDateTime = new ZonedDateTime(now, zone);
bool isDST = zonedDateTime.IsDaylightSavingTime();
person Stephen Kennedy    schedule 17.04.2018

Чтобы освоить преобразование из одного часового пояса в другой, вам нужно посмотреть, что поддерживается (как?), а что нет.

foreach (var tz in TimeZoneInfo.GetSystemTimeZones())
{
    Console.WriteLine("TimeZone Offset: {0} Name : {1}, Supports DLS: {2}", tz.BaseUtcOffset,tz.StandardName,tz.SupportsDaylightSavingTime);
}

Это должно дать вам список всех часовых поясов, включая информацию о DayLightSaving. Заметь:

Смещение часового пояса: 00:00:00 Имя: стандартное время по Гринвичу, поддерживает DLS: False

Смещение часового пояса: 00:00:00 Имя: стандартное время по Гринвичу, поддерживает DLS: True

Поэтому вам нужно использовать «Стандартное время по Гринвичу», потому что оно уже поддерживает переход на летнее время. Никакой работы не нужно делать.

Вот пример кода:

private static string GetBSTTimeStamp(string timestamp)
{
    DateTime dt = DateTime.Parse(timestamp);
    //TimeZoneInfo bst = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
    //Console.WriteLine("Time zone supports dls? {0}", bst.SupportsDaylightSavingTime);
    //Console.WriteLine("Time zone offset? {0}", bst.BaseUtcOffset);
    DateTime dateTimeInUtc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(dt, "Eastern Standard Time", "GMT Standard Time");
    return dateTimeInUtc.ToString();
}
person Taky Djarou    schedule 08.09.2016