функция для преобразования времени между использованием страны / города вместо кода часового пояса - PullRequest
1 голос
/ 01 ноября 2011

Я пишу программу на C # для конвертации времени из разных стран (что-то вроде this ). После треккинга через переполнение стека большинство людей, похоже, заинтересованы в конвертации с использованием кодов часовых поясов (например, от GMT до EDT или от EST до BST). Это выглядит немного странно, потому что вам нужно пройти еще одно препятствие, чтобы учесть осложнения DST.

Что было бы гораздо проще (и более практично, по крайней мере для моих целей), это просто указать страну / город / штат, в который вы хотите перевести время из / в. Если вместо этого мы сейчас просто сосредоточимся на местном времени, я создал эти 2 функции для преобразования из местного времени в FileTime (по существу, в UTC) и обратно.

// Example use: convert_LocalToFile("1/11/2011 00:00:00") = 129645792000000000
long convert_LocalToFile(string time)
{
    DateTime dt = DateTime.Parse(time);
    return dt.ToFileTime();
}
// Example use: convert_FileToLocal(129645792000000000) = "1/11/2011 00:00:00"
string convert_FileToLocal(long time)
{
    return DateTime.FromFileTime(time).ToString();
}

Однако было бы замечательно, если бы мы решили это раз и навсегда, и имели функции, позволяющие вам также указать страну / город. Спецификация будет выглядеть следующим образом:

// Example use 1: convert_AnyToFile("1/11/2011 00:00:00", "England") = 129645792000000000
// Example use 2: convert_AnyToFile("1/11/2011 00:00:00","New York") = 129645936000000000
long convert_AnyToFile(string time, string location) {
    ...
}

// Example use 1: convert_FileToAny(129645792000000000, "England") = "1/11/2011 00:00:00"
// Example use 2: convert_FileToAny(129645936000000000,"New York") = "1/11/2011 00:00:00"
string convert_FileToAny(long time, string location) {
    ...
}

Так что мой вопрос двоякий: может ли кто-нибудь «заполнить» две вышеупомянутые пустые функции, чтобы они работали, а также предоставить C # список всех стран и городов, которые будут разрешены в качестве параметров.

------------------------ РЕДАКТИРОВАТЬ: Вместо страны или города, я бы тоже обошелся с неясным (для меня в любом случае) TZ коды, как показано на этой странице: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Как уже указывалось, мне нужно будет найти файл данных для сопоставления кода базы данных tz с страной / городом / регионом. В этом случае замените «расположение строки» в вышеупомянутых 2 шаблонах функций на «код строки». «код» означает код часового пояса базы данных tz (TZ), а не типичный код часового пояса * (например, EST или GMT).

Ответы [ 3 ]

1 голос
/ 01 ноября 2011

Если вы согласны использовать имена zoneinfo / Olson (например, «Europe / London», «America / Los_Angeles» и т. Д.), Вы можете посмотреть на проект, который я начал, Noda Time . Обычно это порт календарного механизма Joda Time , но с новым API, который будет более .NET-ориентированным.

Это не на v1 еще из-за нескольких отсутствующих функций, но то, что там, должно работать достаточно хорошо. Обратите внимание, что он устраняет многие из недостатков DateTime, в частности, проводит различие между «локальной датой / временем» и «зонированной датой / временем» (а также справляется с просто время или просто дата). Существуют преобразования в и из DateTime, если вы только хотите использовать Noda Time для преобразований часовых поясов, конечно - хотя я рекомендую использовать его повсеместно в вашем коде, если вы можете. (И там, где он не предоставляет все необходимые функции, пожалуйста, сообщите нам, чтобы мы могли добавить их!)

Обратите внимание, что, рассматривая местное время как находящееся в определенном часовом поясе, вы должны знать о возможности того, что оно может быть либо неоднозначным, либо никогда не существовать. Например, в воскресенье часы вернулись в Великобританию, поэтому в 1:30 утра произошло дважды . Весной 1:30 не произойдет вообще, так как часы идут с 1 утра до 2 утра. Конечно, Noda Time предоставляет различные варианты для решения этой проблемы, но вам нужно определиться с тем, что вы хотите сделать в каждом случае:)

1 голос
/ 03 ноября 2011

Как было указано в подобном вопросе , нужно быть осторожным, поскольку Windows использует очень вводящие в заблуждение имена (например: странное «романтическое стандартное время» для Европы / Парижа или «восточное стандартное время» "который странным образом действует как ET и использует летнее время, когда официальное определение говорит об обратном. Не говоря уже о восточное стандартное время США ).

Что касается отображения городов / штатов / стран из часовых поясов Windows, я еще не нашел никакого файла данных для этого, но я буду продолжать поиск. Я предполагаю, что может потребоваться найти данные для преобразования из часовых поясов Windows в часовые пояса Олсона, а затем оттуда в отдельные города / штаты / названия стран. Эта ссылка поможет с первым: http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html

Имея это в виду, я заполнил пустые функции из основного вопроса (спасибо Jon и Yahia за указатели). Первая - это основная функция, которая будет полезна большинству людей. Две другие являются вторичными функциями, которые использует первая функция.

Я проверил их, и они работают на летнее время, хотя держу пари, что Джон Скит и другие смогут найти что-то вроде «незначительных» недостатков. Например, даты до 1601 года не будут работать, так как File Time Windows не поддерживает это. Также рекомендуется заключать вызовы этих функций в операторы try / catch, конечно, чтобы перехватывать ввод ложных данных и т. Д.

// Master conversion function
// Example use 1: convertTimezone("1/11/2011 00:00:00", "GMT Standard Time", "Eastern Standard Time") = "31/10/2011 20:00:00"
// Example use 2: convertTimezone("1/11/2011 00:00:00", "Eastern Standard Time", "GMT Standard Time") = "01/11/2011 04:00:00"
// Example use 3: convertTimezone("1/10/2011 00:00:00", "Eastern Standard Time", "GMT Standard Time") = "01/10/2011 05:00:00"
string convertTimezone(string time, string oldlocation, string newlocation)
{
    long l = convertTime_AnyToFile(time, oldlocation);
    string newtime = convertTime_FileToAny(l, newlocation);
    return newtime;
}

// Example use 1: convertTime_AnyToFile("1/11/2011 00:00:00", "GMT Standard Time") =    129645792000000000
// Example use 2: convertTime_AnyToFile("1/11/2011 00:00:00","Eastern Standard Time") = 129645936000000000
long convertTime_AnyToFile(string time, string location)
{
    DateTime a = DateTime.Parse(time  );
    DateTime b = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(a, location, "UTC");
    return b.ToFileTime();
}

// Example use 1: convertTime_FileToAny(129645792000000000, "GMT Standard Time") = "1/11/2011 00:00:00"
// Example use 2: convertTime_FileToAny(129645936000000000,"Eastern Standard Time") = "1/11/2011 00:00:00"
string convertTime_FileToAny(long time, string location)
{
    DateTime a = DateTime.FromFileTimeUtc(time);
    DateTime b = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(a, location);
    return b.ToString();
}

Несмотря на то, что он работает нормально (в рамках ограниченных тестов, которые я провел), прежде чем «поставить галочку» на своем собственном ответе, я мог бы сначала подождать некоторого отзыва, поскольку, возможно, кто-то сможет улучшить приведенный выше код.

1 голос
/ 01 ноября 2011

Согласно комментариям некоторые указатели:

Код конверсии см. В Создание DateTime в определенном часовом поясе в c # fx 3.5 и http://www.jarloo.com/c-convert-timezones/.

Код для обработки часовых поясов, как в tz_database (он же Olson ...), см. http://www.twinsun.com/tz/tz-link.htm и http://www.codeproject.com/KB/dotnet/Using_time_zones_in_NET.aspx.

Ссылки MSDN на соответствующие классы / методы и т. Д. :

ОБНОВЛЕНИЕ

После прочтения о NodaTime (даже не подозревая о его существовании) я настоятельно рекомендую его использовать - см. Ответ Джона Скита.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...