Я использую TimeZoneInfo для преобразования между клиентским стендом "Восточное время" и UTC. Моя проблема связана с "повторяющимся" часом, который происходит во время осеннего перехода на летнее время.
Во время перехода от UTC к востоку:
2010-11-07 06:00 UTC → дает 2010-11-07T 01: 00: 00-03: 30
2010-11-07 07:00 UTC → дает 2010-11-07T 01: 00: 00-03: 30
Как я могу узнать, что такое первый час, а второй? DateTime.IsDaylightSavingTime() возвращает false для обоих часов, но не должен ли он возвращать true в течение первого часа?
Аналогично, как я могу хранить 2010-11-07 01:00:00 -03: 30? Как мое приложение может конвертировать в UTC, так как это может быть 2010-11-07 06: 00 или 2010-11-07 07: 00
Для тех, кто нуждается в коде, я езжу на велосипеде через datatable с столбцом datetime UTC, пытаясь конвертировать в Eastern с колонкой "DupHr" для второго повторяющегося часа, но я всегда заканчиваю оба 01:00 часов, DupHr '= 1.
TimeZoneInfo est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime EasternTime;
DateTime DuplicateHour = new DateTime(2010, 11, 7, 1, 0, 0); // hard coded for this example
TimeZoneInfo.AdjustmentRule[] rules = est.GetAdjustmentRules();
foreach (DataRow row in dt.Rows)
{
row["DupHr"] = 0; // by default not duplicate hour
EasternTime = TimeZoneInfo.ConvertTimeFromUtc((DateTime)row[UTCColumnName], est);
if (!EasternTime.IsDaylightSavingTime())
{
if (EasternTime.Equals(DuplicateHour ))
{
row["DupHr"] = 1; // This is the second duplicate hour !
}
} else
EasternTime.Add(rules[1].DaylightDelta); // Add DST offset from rule #1
row[newESTColumnName] = EasternTime;
}
СПАСИБО!
Решение
Важно знать больше, чем "неоднозначное" для повторяющихся часов. Часы должны быть уникальными (первый и второй). Рассмотрите приложение счетчика денежных средств, которое должно работать 24x7 и суммировать каждую часовую коллекцию. Деньги, собранные в каждый час, должны быть идентифицируемы. Первый час с 1:00 до 1:59 отличается от второго 1:00 до 1:59 часа. Процедура ниже isSecondHour вернет значение true, только если прошедшее время находится в second часе осеннего перехода на летнее время. Пользовательский интерфейс может отображать этот флаг соответствующим образом.
// Get the DST rule for the year and zone (rules may change from year to year as in 2004)
public static TimeZoneInfo.AdjustmentRule GetDSTrule(int Year, TimeZoneInfo zone)
{
TimeZoneInfo.AdjustmentRule[] rules = zone.GetAdjustmentRules();
foreach (TimeZoneInfo.AdjustmentRule rul in rules)
{
if (rul.DateStart < new DateTime(Year, 1, 1) && rul.DateEnd > new DateTime(Year, 1, 1))
{
return rul;
}
}
return null;
}
// Determine if 'localtime' is in the second duplicate DST hour.
public static Boolean isSecondHour(TimeZoneInfo localzone, DateTime localtime, DateTime UTCtime)
{
if (localzone.IsAmbiguousTime(localtime))
{
TimeZoneInfo.AdjustmentRule rul = GetDSTrule(localtime.Year, localzone);
return UTCtime.Add(localzone.GetUtcOffset(localtime)) == localtime;
}
else
return false;
}
static void Main(string[] args)
{
var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var times = new DateTime[] {
new DateTime (2010, 11, 7, 3, 0, 0, DateTimeKind.Unspecified),
new DateTime (2010, 11, 7, 4, 0, 0, DateTimeKind.Unspecified),
new DateTime (2010, 11, 7, 5, 0, 0, DateTimeKind.Unspecified),
new DateTime (2010, 11, 7, 5, 30, 0, DateTimeKind.Unspecified),
new DateTime (2010, 11, 7, 6, 0, 0, DateTimeKind.Unspecified),
new DateTime (2010, 11, 7, 6, 30, 0, DateTimeKind.Unspecified),
new DateTime (2010, 11, 7, 7, 0, 0, DateTimeKind.Unspecified),
new DateTime (2010, 11, 7, 8, 0, 0, DateTimeKind.Unspecified)
};
DateTime EasternTime;
Console.WriteLine("UTC Time | Est Time | IsDaylightSaving | IsAmbiguousTime | isSecondHour ");
foreach (var utc in times)
{
// Get Eastern Time from UTC using standard convert routine.
EasternTime = TimeZoneInfo.ConvertTimeFromUtc(utc, est);
Console.WriteLine("{0:HH:mm} | {1:HH:mm} | {2,11} | {3,5} | {4,5}", utc,EasternTime, est.IsDaylightSavingTime(EasternTime), est.IsAmbiguousTime(EasternTime),isSecondHour(est,EasternTime, utc));
}
Результаты
UTC Time | Est Time | IsDaylightSaving | IsAmbiguousTime | isSecondHour
03:00 | 23:00 | True | False | False
04:00 | 00:00 | True | False | False
05:00 | 01:00 | False | True | False
05:30 | 01:30 | False | True | False
06:00 | 01:00 | False | True | True
06:30 | 01:30 | False | True | True
07:00 | 02:00 | False | False | False
08:00 | 03:00 | False | False | False