Перейти к содержимому

Напишите функцию которая по названию города скажет сколько там сейчас времени

  • автор:

3. Стандарт UTC (Библиотеки)

Юн Сергей

Напишите функцию, которая по названию города скажет, сколько там сейчас времени.

Мы заготовили словарь UTC_OFFSET (англ. offset, «сдвиг»), где для каждого города записана разница местного времени и UTC в часах.

Код:

import datetime as dt UTC_OFFSET = < 'Санкт-Петербург': 3, 'Москва': 3, 'Самара': 4, 'Новосибирск': 7, 'Екатеринбург': 5, 'Нижний Новгород': 3, 'Казань': 3, 'Челябинск': 5, 'Омск': 6, 'Ростов-на-Дону': 3, 'Уфа': 5, 'Красноярск': 7, 'Пермь': 5, 'Воронеж': 3, 'Волгоград': 4, 'Краснодар': 3, 'Калининград': 2 >def what_time(city): # напишите код тела функции # пусть она вернет время в городе city time_in_city = dt.timedelta(hours=UTC_OFFSET [city]) + dt.datetime.utcnow() return time_in_city print(what_time('Екатеринбург')) 

Результат:

2019-11-21 19:03:28.447966

Задача 2

Напишите функцию, которая по имени друга скажет, сколько у него сейчас времени.

В словаре DATABASE хранятся данные о том, кто из друзей где живёт.

Код:

import datetime as dt DATABASE = < 'Серёга': 'Омск', 'Соня': 'Москва', 'Дима': 'Челябинск', 'Алина': 'Красноярск', 'Егор': 'Пермь' >UTC_OFFSET = < 'Санкт-Петербург': 3, 'Москва': 3, 'Самара': 4, 'Новосибирск': 7, 'Екатеринбург': 5, 'Нижний Новгород': 3, 'Казань': 3, 'Челябинск': 5, 'Омск': 6, 'Ростов-на-Дону': 3, 'Уфа': 5, 'Красноярск': 7, 'Пермь': 5, 'Воронеж': 3, 'Волгоград': 4, 'Краснодар': 3, 'Калининград': 2 >def what_time(friend): # напишите код тела функции # пусть она вернет время у друга из аргумента friend city = DATABASE [friend] current_time = dt.datetime.utcnow() + dt.timedelta (hours=UTC_OFFSET[city]) return current_time print(what_time('Алина'))

Результат:

2019-11-21 21:10:06.632558

Генераторы

Обычные функции возвращают только одно-единственное значение (или ничего).

Генераторы могут порождать (yield) множество значений одно за другим, по мере необходимости. Генераторы отлично работают с перебираемыми объектами и позволяют легко создавать потоки данных.

Функция-генератор

Для объявления генератора используется специальная синтаксическая конструкция: function* , которая называется «функция-генератор».

Выглядит она так:

function* generateSequence()

Функции-генераторы ведут себя не так, как обычные. Когда такая функция вызвана, она не выполняет свой код. Вместо этого она возвращает специальный объект, так называемый «генератор», для управления её выполнением.

function* generateSequence() < yield 1; yield 2; return 3; >// "функция-генератор" создаёт объект "генератор" let generator = generateSequence(); alert(generator); // [object Generator]

Выполнение кода функции ещё не началось:

Основным методом генератора является next() . При вызове он запускает выполнение кода до ближайшей инструкции yield (значение может отсутствовать, в этом случае оно предполагается равным undefined ). По достижении yield выполнение функции приостанавливается, а соответствующее значение – возвращается во внешний код:

Результатом метода next() всегда является объект с двумя свойствами:

  • value : значение из yield .
  • done : true , если выполнение функции завершено, иначе false .

Например, здесь мы создаём генератор и получаем первое из возвращаемых им значений:

function* generateSequence() < yield 1; yield 2; return 3; >let generator = generateSequence(); let one = generator.next(); alert(JSON.stringify(one)); //

На данный момент мы получили только первое значение, выполнение функции остановлено на второй строке:

Повторный вызов generator.next() возобновит выполнение кода и вернёт результат следующего yield :

let two = generator.next(); alert(JSON.stringify(two)); //

И, наконец, последний вызов завершит выполнение функции и вернёт результат return :

let three = generator.next(); alert(JSON.stringify(three)); //

Сейчас генератор полностью выполнен. Мы можем увидеть это по свойству done:true и обработать value:3 как окончательный результат.

Новые вызовы generator.next() больше не имеют смысла. Впрочем, если они и будут, то не вызовут ошибки, но будут возвращать один и тот же объект: .

function* f(…) или function *f(…) ?

Нет разницы, оба синтаксиса корректны.

Но обычно предпочтителен первый вариант, так как звёздочка относится к типу объявляемой сущности ( function* – «функция-генератор»), а не к её названию, так что резонно расположить её у слова function .

Перебор генераторов

Как вы, наверное, уже догадались по наличию метода next() , генераторы являются перебираемыми объектами.

Возвращаемые ими значения можно перебирать через for..of :

function* generateSequence() < yield 1; yield 2; return 3; >let generator = generateSequence(); for(let value of generator) < alert(value); // 1, затем 2 >

Выглядит гораздо красивее, чем использование .next().value , верно?

…Но обратите внимание: пример выше выводит значение 1 , затем 2 . Значение 3 выведено не будет!

Это из-за того, что перебор через for..of игнорирует последнее значение, при котором done: true . Поэтому, если мы хотим, чтобы были все значения при переборе через for..of , то надо возвращать их через yield :

function* generateSequence() < yield 1; yield 2; yield 3; >let generator = generateSequence(); for(let value of generator) < alert(value); // 1, затем 2, затем 3 >

Так как генераторы являются перебираемыми объектами, мы можем использовать всю связанную с ними функциональность, например оператор расширения . :

function* generateSequence() < yield 1; yield 2; yield 3; >let sequence = [0, . generateSequence()]; alert(sequence); // 0, 1, 2, 3

В коде выше . generateSequence() превращает перебираемый объект-генератор в массив элементов (подробнее ознакомиться с оператором расширения можно в главе Остаточные параметры и оператор расширения)

Использование генераторов для перебираемых объектов

Некоторое время назад, в главе Перебираемые объекты, мы создали перебираемый объект range , который возвращает значения from..to .

Давайте вспомним код:

let range = < from: 1, to: 5, // for..of range вызывает этот метод один раз в самом начале [Symbol.iterator]() < // . он возвращает перебираемый объект: // далее for..of работает только с этим объектом, запрашивая следующие значения return < current: this.from, last: this.to, // next() вызывается при каждой итерации цикла for..of next() < // нужно вернуть значение как объект if (this.current ; > else < return < done: true >; > > >; > >; // при переборе объекта range будут выведены числа от range.from до range.to alert([. range]); // 1,2,3,4,5

Мы можем использовать функцию-генератор для итерации, указав её в Symbol.iterator .

Вот тот же range , но с гораздо более компактным итератором:

let range = < from: 1, to: 5, *[Symbol.iterator]() < // краткая запись для [Symbol.iterator]: function*() for(let value = this.from; value > >; alert( [. range] ); // 1,2,3,4,5

Это работает, потому что range[Symbol.iterator]() теперь возвращает генератор, и его методы – в точности то, что ожидает for..of :

  • у него есть метод .next()
  • который возвращает значения в виде

Это не совпадение, конечно. Генераторы были добавлены в язык JavaScript, в частности, с целью упростить создание перебираемых объектов.

Вариант с генератором намного короче, чем исходный вариант перебираемого range , и сохраняет те же функциональные возможности.

Генераторы могут генерировать бесконечно

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

Конечно, нам потребуется break (или return ) в цикле for..of по такому генератору, иначе цикл будет продолжаться бесконечно, и скрипт «зависнет».

Композиция генераторов

Композиция генераторов – это особенная возможность генераторов, которая позволяет прозрачно «встраивать» генераторы друг в друга.

Например, у нас есть функция для генерации последовательности чисел:

function* generateSequence(start, end)

Мы хотели бы использовать её при генерации более сложной последовательности:

  • сначала цифры 0..9 (с кодами символов 48…57)
  • за которыми следуют буквы в верхнем регистре A..Z (коды символов 65…90)
  • за которыми следуют буквы алфавита a..z (коды символов 97…122)

Мы можем использовать такую последовательность для генерации паролей, выбирать символы из неё (может быть, ещё добавить символы пунктуации), но сначала её нужно сгенерировать.

В обычной функции, чтобы объединить результаты из нескольких других функций, мы вызываем их, сохраняем промежуточные результаты, а затем в конце их объединяем.

Для генераторов есть особый синтаксис yield* , который позволяет «вкладывать» генераторы один в другой (осуществлять их композицию).

Вот генератор с композицией:

function* generateSequence(start, end) < for (let i = start; i function* generatePasswordCodes() < // 0..9 yield* generateSequence(48, 57); // A..Z yield* generateSequence(65, 90); // a..z yield* generateSequence(97, 122); >let str = ''; for(let code of generatePasswordCodes()) < str += String.fromCharCode(code); >alert(str); // 0..9A..Za..z

Директива yield* делегирует выполнение другому генератору. Этот термин означает, что yield* gen перебирает генератор gen и прозрачно направляет его вывод наружу. Как если бы значения были сгенерированы внешним генератором.

Результат – такой же, как если бы мы встроили код из вложенных генераторов:

function* generateSequence(start, end) < for (let i = start; i function* generateAlphaNum() < // yield* generateSequence(48, 57); for (let i = 48; i let str = ''; for(let code of generateAlphaNum()) < str += String.fromCharCode(code); >alert(str); // 0..9a..zA..Z

Композиция генераторов – естественный способ вставлять вывод одного генератора в поток другого. Она не использует дополнительную память для хранения промежуточных результатов.

yield – дорога в обе стороны

До этого момента генераторы сильно напоминали перебираемые объекты, со специальным синтаксисом для генерации значений. Но на самом деле они намного мощнее и гибче.

Всё дело в том, что yield – дорога в обе стороны: он не только возвращает результат наружу, но и может передавать значение извне в генератор.

Чтобы это сделать, нам нужно вызвать generator.next(arg) с аргументом. Этот аргумент становится результатом yield .

Продемонстрируем это на примере:

function* gen() < // Передаём вопрос во внешний код и ожидаем ответа let result = yield "2 + 2 = ?"; // (*) alert(result); >let generator = gen(); let question = generator.next().value; // передаём результат в генератор
  1. Первый вызов generator.next() – всегда без аргумента, он начинает выполнение и возвращает результат первого yield «2+2=?» . На этой точке генератор приостанавливает выполнение.
  2. Затем, как показано на картинке выше, результат yield переходит во внешний код в переменную question .
  3. При generator.next(4) выполнение генератора возобновляется, а 4 выходит из присваивания как результат: let result = 4 .

Обратите внимание, что внешний код не обязан немедленно вызывать next(4) . Ему может потребоваться время. Это не проблема, генератор подождёт.

// возобновить генератор через некоторое время setTimeout(() => generator.next(4), 1000);

Как видно, в отличие от обычных функций, генератор может обмениваться результатами с вызывающим кодом, передавая значения в next/yield .

Чтобы сделать происходящее более очевидным, вот ещё один пример с большим количеством вызовов:

function* gen() < let ask1 = yield "2 + 2 = ?"; alert(ask1); // 4 let ask2 = yield "3 * 3 = ?" alert(ask2); // 9 >let generator = gen(); alert( generator.next().value ); // "2 + 2 = ?" alert( generator.next(4).value ); // "3 * 3 = ?" alert( generator.next(9).done ); // true
  1. Первый .next() начинает выполнение… Оно доходит до первого yield .
  2. Результат возвращается во внешний код.
  3. Второй .next(4) передаёт 4 обратно в генератор как результат первого yield и возобновляет выполнение.
  4. …Оно доходит до второго yield , который станет результатом .next(4) .
  5. Третий next(9) передаёт 9 в генератор как результат второго yield и возобновляет выполнение, которое завершается окончанием функции, так что done: true .

Получается такой «пинг-понг»: каждый next(value) передаёт в генератор значение, которое становится результатом текущего yield , возобновляет выполнение и получает выражение из следующего yield .

generator.throw

Как мы видели в примерах выше, внешний код может передавать значение в генератор как результат yield .

…Но можно передать не только результат, но и инициировать ошибку. Это естественно, так как ошибка является своего рода результатом.

Для того, чтобы передать ошибку в yield , нам нужно вызвать generator.throw(err) . В таком случае исключение err возникнет на строке с yield .

Например, здесь yield «2 + 2 = ?» приведёт к ошибке:

function* gen() < try < let result = yield "2 + 2 = ?"; // (1) alert("Выполнение программы не дойдёт до этой строки, потому что выше возникнет исключение"); >catch(e) < alert(e); // покажет ошибку >> let generator = gen(); let question = generator.next().value; generator.throw(new Error("Ответ не найден в моей базе данных")); // (2)

Ошибка, которая проброшена в генератор на строке (2) , приводит к исключению на строке (1) с yield . В примере выше try..catch перехватывает её и отображает.

Если мы не хотим перехватывать её, то она, как и любое обычное исключение, «вывалится» из генератора во внешний код.

Текущая строка вызывающего кода – это строка с generator.throw , отмечена (2) . Таким образом, мы можем отловить её во внешнем коде, как здесь:

function* generate() < let result = yield "2 + 2 = ?"; // Ошибка в этой строке >let generator = generate(); let question = generator.next().value; try < generator.throw(new Error("Ответ не найден в моей базе данных")); >catch(e) < alert(e); // покажет ошибку >

Если же ошибка и там не перехвачена, то дальше – как обычно, она выпадает наружу и, если не перехвачена, «повалит» скрипт.

Итого

  • Генераторы создаются при помощи функций-генераторов function* f(…) .
  • Внутри генераторов и только внутри них существует оператор yield .
  • Внешний код и генератор обмениваются промежуточными результатами посредством вызовов next/yield .

В современном JavaScript генераторы используются редко. Но иногда они оказываются полезными, потому что способность функции обмениваться данными с вызывающим кодом во время выполнения совершенно уникальна. И, конечно, для создания перебираемых объектов.

Также, в следующей главе мы будем изучать асинхронные генераторы, которые используются, чтобы читать потоки асинхронно сгенерированных данных (например, постранично загружаемые из сети) в цикле for await . of .

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

Задачи

Псевдослучайный генератор

Есть много областей, где нам нужны случайные данные.

Одной из них является тестирование. Нам могут понадобиться случайные данные: текст, числа и т.д., чтобы хорошо всё проверить.

В JavaScript мы можем использовать Math.random() . Но если что-то пойдёт не так, то нам нужно будет перезапустить тест, используя те же самые данные.

Для этого используются так называемые «сеяные псевдослучайные генераторы». Они получают «зерно», как первое значение, и затем генерируют следующее, используя формулу. Так что одно и то же зерно даёт одинаковую последовательность, и, следовательно, весь поток легко воспроизводим. Нам нужно только запомнить зерно, чтобы воспроизвести последовательность.

Пример такой формулы, которая генерирует более-менее равномерно распределённые значения:

next = previous * 16807 % 2147483647

Если мы используем 1 как зерно, то значения будут:

  1. 16807
  2. 282475249
  3. 1622650073
  4. …и так далее…

Задачей является создать функцию-генератор pseudoRandom(seed) , которая получает seed и создаёт генератор с указанной формулой.

let generator = pseudoRandom(1); alert(generator.next().value); // 16807 alert(generator.next().value); // 282475249 alert(generator.next().value); // 1622650073

Преобразование времени из одного часового пояса в другой

Это становится все более важным для любого приложения, которое работает с датами и временем для обработки различий между часовыми поясами. Приложение больше не может предполагать, что все время может быть выражено в местном времени, которое является временем, доступным в DateTime структуре. Например, веб-страница, на котором отображается текущее время в восточной части США, будет не доверяет клиенту в восточной Азии. В этой статье объясняется, как преобразовать время из одного часового пояса в другой и преобразовать DateTimeOffset значения с ограниченной осведомленностью о часовых поясах.

Преобразование во время в формате UTC

Время в формате UTC — это высокоточный, атомарный стандарт времени. Часовые пояса в мире выражаются как положительные или отрицательные смещения от UTC. Таким образом, в формате UTC предоставляется время без часового пояса или нейтральное время с часового пояса. Использование UTC рекомендуется, если важна переносимость даты и времени между компьютерами. Дополнительные сведения и другие рекомендации по использованию дат и времени см. в статье Рекомендации по написанию кода с помощью даты и времени в платформа .NET Framework. Преобразование отдельных часовых поясов во время в формате UTC упрощает сравнение времен.

Вы также можете сериализовать структуру DateTimeOffset , чтобы однозначно представить одну точку во времени. Поскольку DateTimeOffset объекты хранят значение даты и времени вместе со смещением от UTC, они всегда представляют определенную точку во времени по отношению к utc.

Самый простой способ преобразовать время в формат UTC — вызвать static метод ( Shared в Visual Basic). TimeZoneInfo.ConvertTimeToUtc(DateTime) Точное преобразование, выполняемое методом , зависит от значения dateTime свойства параметра Kind , как показано в следующей таблице:

DateTime.Kind Преобразование
DateTimeKind.Local Преобразует местное время во время в формате UTC.
DateTimeKind.Unspecified Предполагает, что параметр dateTime является местным временем и преобразовывает местное время в UTC.
DateTimeKind.Utc Возвращает неизмененный параметр dateTime .

Следующий код преобразует текущее местное время в формат UTC и отображает результат в консоли:

DateTime dateNow = DateTime.Now; Console.WriteLine("The date and time are UTC.", TimeZoneInfo.ConvertTimeToUtc(dateNow)); 
Dim dateNow As Date = Date.Now Console.WriteLine("The date and time are UTC.", _ TimeZoneInfo.ConvertTimeToUtc(dateNow)) 

Если значение даты и времени не представляет местное время или время в формате UTC, метод, скорее всего, ToUniversalTime вернет ошибочный результат. Однако можно использовать метод для TimeZoneInfo.ConvertTimeToUtc преобразования даты и времени из указанного часового пояса. Дополнительные сведения о получении объекта, представляющего TimeZoneInfo часовой пояс назначения, см. в разделе Поиск часовых поясов, определенных в локальной системе. В следующем коде TimeZoneInfo.ConvertTimeToUtc используется метод для преобразования восточного стандартного времени в формат UTC:

DateTime easternTime = new DateTime(2007, 01, 02, 12, 16, 00); string easternZoneId = "Eastern Standard Time"; try < TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId); Console.WriteLine("The date and time are UTC.", TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)); > catch (TimeZoneNotFoundException) < Console.WriteLine("Unable to find the zone in the registry.", easternZoneId); > catch (InvalidTimeZoneException) < Console.WriteLine("Registry data on the zone has been corrupted.", easternZoneId); > 
Dim easternTime As New Date(2007, 01, 02, 12, 16, 00) Dim easternZoneId As String = "Eastern Standard Time" Try Dim easternZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId) Console.WriteLine("The date and time are UTC.", _ TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)) Catch e As TimeZoneNotFoundException Console.WriteLine("Unable to find the zone in the registry.", _ easternZoneId) Catch e As InvalidTimeZoneException Console.WriteLine("Registry data on the zone has been corrupted.", _ easternZoneId) End Try 

Метод TimeZoneInfo.ConvertTimeToUtc создает исключение , ArgumentException если DateTime свойство объекта Kind и часовой пояс не совпадают. Несоответствие возникает, если Kind свойство имеет значение , DateTimeKind.Local но TimeZoneInfo объект не представляет локальный часовой пояс, или если Kind свойство имеет значение DateTimeKind.Utc , но TimeZoneInfo объект не равен TimeZoneInfo.Utc.

Все эти методы принимают DateTime значения в качестве параметров и возвращают DateTime значение. Для DateTimeOffset значений структура DateTimeOffset имеет метод экземпляра ToUniversalTime , который преобразует дату и время текущего экземпляра в формат UTC. В следующем примере вызывается ToUniversalTime метод для преобразования местного времени и нескольких других раз в формат UTC:

DateTimeOffset localTime, otherTime, universalTime; // Define local time in local time zone localTime = new DateTimeOffset(new DateTime(2007, 6, 15, 12, 0, 0)); Console.WriteLine("Local time: ", localTime); Console.WriteLine(); // Convert local time to offset 0 and assign to otherTime otherTime = localTime.ToOffset(TimeSpan.Zero); Console.WriteLine("Other time: ", otherTime); Console.WriteLine(" = : ", localTime, otherTime, localTime.Equals(otherTime)); Console.WriteLine(" exactly equals : ", localTime, otherTime, localTime.EqualsExact(otherTime)); Console.WriteLine(); // Convert other time to UTC universalTime = localTime.ToUniversalTime(); Console.WriteLine("Universal time: ", universalTime); Console.WriteLine(" = : ", otherTime, universalTime, universalTime.Equals(otherTime)); Console.WriteLine(" exactly equals : ", otherTime, universalTime, universalTime.EqualsExact(otherTime)); Console.WriteLine(); // The example produces the following output to the console: // Local time: 6/15/2007 12:00:00 PM -07:00 // // Other time: 6/15/2007 7:00:00 PM +00:00 // 6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True // 6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False // // Universal time: 6/15/2007 7:00:00 PM +00:00 // 6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True // 6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True 
Dim localTime, otherTime, universalTime As DateTimeOffset ' Define local time in local time zone localTime = New DateTimeOffset(#6/15/2007 12:00:00PM#) Console.WriteLine("Local time: ", localTime) Console.WriteLine() ' Convert local time to offset 0 and assign to otherTime otherTime = localTime.ToOffset(TimeSpan.Zero) Console.WriteLine("Other time: ", otherTime) Console.WriteLine(" = : ", _ localTime, otherTime, _ localTime.Equals(otherTime)) Console.WriteLine(" exactly equals : ", _ localTime, otherTime, _ localTime.EqualsExact(otherTime)) Console.WriteLine() ' Convert other time to UTC universalTime = localTime.ToUniversalTime() Console.WriteLine("Universal time: ", universalTime) Console.WriteLine(" = : ", _ otherTime, universalTime, _ universalTime.Equals(otherTime)) Console.WriteLine(" exactly equals : ", _ otherTime, universalTime, _ universalTime.EqualsExact(otherTime)) Console.WriteLine() ' The example produces the following output to the console: ' Local time: 6/15/2007 12:00:00 PM -07:00 ' ' Other time: 6/15/2007 7:00:00 PM +00:00 ' 6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True ' 6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False ' ' Universal time: 6/15/2007 7:00:00 PM +00:00 ' 6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True ' 6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True 

Преобразование времени в формате UTC в заданный часовой пояс

Чтобы преобразовать время в формате UTC в местное, см. информацию в разделе Преобразование времени в формате UTC в местное время. Чтобы преобразовать время в формате UTC в любом назначенном часовом поясе, вызовите ConvertTimeFromUtc метод . Этот метод принимает два параметра:

  • Время в формате UTC, которое требуется преобразовать. Это должно быть значение, DateTime свойство которого Kind имеет значение Unspecified или Utc .
  • Часовой пояс, в который требуется преобразовать время в формате UTC.

Следующий код преобразует время UTC в центральное стандартное время:

DateTime timeUtc = DateTime.UtcNow; try < TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone); Console.WriteLine("The date and time are .", cstTime, cstZone.IsDaylightSavingTime(cstTime) ? cstZone.DaylightName : cstZone.StandardName); > catch (TimeZoneNotFoundException) < Console.WriteLine("The registry does not define the Central Standard Time zone."); >catch (InvalidTimeZoneException)
Dim timeUtc As Date = Date.UtcNow Try Dim cstZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time") Dim cstTime As Date = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone) Console.WriteLine("The date and time are .", _ cstTime, _ IIf(cstZone.IsDaylightSavingTime(cstTime), _ cstZone.DaylightName, cstZone.StandardName)) Catch e As TimeZoneNotFoundException Console.WriteLine("The registry does not define the Central Standard Time zone.") Catch e As InvalidTimeZoneException Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.") End Try 

Преобразование времени в формате UTC в местное время

Чтобы преобразовать время UTC в местное время, вызовите ToLocalTime метод DateTime объекта, время которого требуется преобразовать. Точное поведение метода зависит от значения свойства объекта Kind , как показано в следующей таблице:

DateTime.Kind Преобразование
DateTimeKind.Local DateTime Возвращает значение без изменений.
DateTimeKind.Unspecified Предполагает, что DateTime значение равно UTC, и преобразует время UTC в местное время.
DateTimeKind.Utc Преобразует значение в DateTime местное время.

Метод TimeZone.ToLocalTime ведет себя идентично методу DateTime.ToLocalTime . Для преобразования требуется один параметр, который является значением даты и времени.

Вы также можете преобразовать время в любом указанном часовом поясе в местное время с помощью static метода ( Shared в Visual Basic). TimeZoneInfo.ConvertTime Этот метод рассматривается в следующем разделе.

Преобразование между любыми двумя часовыми поясами

Вы можете выполнить преобразование между любыми двумя часовых поясами с помощью одного из следующих двух static методов TimeZoneInfo ( Shared в Visual Basic) класса :

  • ConvertTime Параметры этого метода — это преобразуемое значение даты и времени, объект, TimeZoneInfo представляющий часовой пояс значения даты и времени, и TimeZoneInfo объект , представляющий часовой пояс, в который необходимо преобразовать значение даты и времени.
  • ConvertTimeBySystemTimeZoneId Параметры этого метода — это преобразуемое значение даты и времени, идентификатор часового пояса значения даты и времени и идентификатор часового пояса, в который преобразуются значения даты и времени.

Оба метода требуют, чтобы Kind свойство значения даты и времени для преобразования, а TimeZoneInfo объект или идентификатор часового пояса, представляющий его часовой пояс, соответствовал друг другу. В противном случае возникает исключение ArgumentException. Например, если Kind свойство значения даты и времени равно DateTimeKind.Local , создается исключение, если TimeZoneInfo объект, передаваемый в качестве параметра в метод, не равен TimeZoneInfo.Local . Исключение также возникает, если идентификатор, переданный в метод в качестве параметра, не равен TimeZoneInfo.Local.Id .

В следующем примере метод используется ConvertTime для преобразования из гавайского стандартного времени в местное время:

DateTime hwTime = new DateTime(2007, 02, 01, 08, 00, 00); try < TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time"); Console.WriteLine(" is local time.", hwTime, hwZone.IsDaylightSavingTime(hwTime) ? hwZone.DaylightName : hwZone.StandardName, TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local)); > catch (TimeZoneNotFoundException) < Console.WriteLine("The registry does not define the Hawaiian Standard Time zone."); >catch (InvalidTimeZoneException)
Dim hwTime As Date = #2/01/2007 8:00:00 AM# Try Dim hwZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time") Console.WriteLine("  is local time.", _ hwTime, _ IIf(hwZone.IsDaylightSavingTime(hwTime), hwZone.DaylightName, hwZone.StandardName), _ TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local)) Catch e As TimeZoneNotFoundException Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.") Catch e As InvalidTimeZoneException Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.") End Try 

Преобразование значений DateTimeOffset

Значения даты и времени, представленные объектами DateTimeOffset , не полностью поддерживают часовой пояс, так как объект не связан с часовыми поясами во время создания экземпляра. Однако во многих случаях приложению просто необходимо преобразовать дату и время на основе двух различных смещений в формате UTC, а не времени в определенных часовых поясах. Для выполнения этого преобразования можно вызвать метод текущего экземпляра ToOffset . Один параметр метода — это смещение нового значения даты и времени, которое будет возвращено методом.

Например, если дата и время запроса пользователя для веб-страницы известны и сериализуются в виде строки в формате ММ/дд/гггг чч:мм:сс zzzz, следующий ReturnTimeOnServer метод преобразует это значение даты и времени в дату и время на веб-сервере:

public DateTimeOffset ReturnTimeOnServer(string clientString) < string format = @"M/d/yyyy H:m:s zzz"; TimeSpan serverOffset = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now); try < DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture); DateTimeOffset serverTime = clientTime.ToOffset(serverOffset); return serverTime; >catch (FormatException) < return DateTimeOffset.MinValue; >> 
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset Dim format As String = "M/d/yyyy H:m:s zzz" Dim serverOffset As TimeSpan = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now) Try Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture) Dim serverTime As DateTimeOffset = clientTime.ToOffset(serverOffset) Return serverTime Catch e As FormatException Return DateTimeOffset.MinValue End Try End Function 

Если метод передает строку «9/1/2007 5:32:07 -05:00», которая представляет дату и время в часовом поясе на пять часов раньше UTC, он возвращает «01.09.2007 3:32:07-07:00» для сервера, расположенного в стандартном часовом поясе США.

Класс TimeZoneInfo также включает перегрузку TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) метода , который выполняет преобразования часовых поясов со значениями ToOffset(TimeSpan) . Параметры метода являются значением DateTimeOffset и ссылкой на часовой пояс, в который необходимо преобразовать время. Вызов метода возвращает DateTimeOffset значение. Например, ReturnTimeOnServer метод в предыдущем примере можно переписать, как показано ниже, чтобы вызвать ConvertTime(DateTimeOffset, TimeZoneInfo) метод .

public DateTimeOffset ReturnTimeOnServer(string clientString) < string format = @"M/d/yyyy H:m:s zzz"; try < DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture); DateTimeOffset serverTime = TimeZoneInfo.ConvertTime(clientTime, TimeZoneInfo.Local); return serverTime; >catch (FormatException) < return DateTimeOffset.MinValue; >> 
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset Dim format As String = "M/d/yyyy H:m:s zzz" Try Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture) Dim serverTime As DateTimeOffset = TimeZoneInfo.ConvertTime(clientTime, TimeZoneInfo.Local) Return serverTime Catch e As FormatException Return DateTimeOffset.MinValue End Try End Function 

См. также раздел

  • TimeZoneInfo
  • Даты, время и часовые пояса
  • Поиск часового пояса, заданного в локальной системе

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Последние заметки

Домашняя работа по курсу Веб-вёрстка от Skillbox

3 года назад

2.7 Домашняя работаЦель заданияПопрактиковаться с HTML-тегами, сверстать первую мини.

Отключение перенаправления файлов Python (Wow64)

4 года назад

Когда 32-разрядная программа выполняется в 64-разрядной операционной системе, пути к.

4. Обработка ошибок (Сетевые запросы)

4 года назад

Задача 1 Напишите функцию what_weather() (англ. «какая погода?»), которую затем будете.

3. Заголовки запросов и ответов (Сетевые запросы)

4 года назад

На прошлом уроке вы заказывали страницу на русском языке через параметры в URL. Сейчас сделайте то.

2. Передаём параметры в URL (Сетевые запросы)

4 года назад

Задача 1 Запросите погодный сервис по URL без параметров. А их задайте словарём weather_parameters.

1. Python вместо браузера (Сетевые запросы )

4 года назад

Пора учить Анфису разговаривать с серверами в обход браузеров. Отработаем этот навык на разговорах.

4. Кириллица в адресной строке (Протокол HTTP)

4 года назад

Вы получили страшный URL. Расшифруйте, какой вопрос задал Яндексу пользователь. В ответ напечатайте.

3. Подробнее об URL (Протокол HTTP)

4 года назад

У вас есть запрос «как стать бэкенд-разработчиком». Соберите URL страницы, на которой.

4. Форматирование времени (Библиотеки)

4 года назад

Задача 1 Сделайте так, чтобы функция what_time() возвращала время в формате часы:минуты. Код.

3. Стандарт UTC (Библиотеки)

4 года назад

Задача 1 Напишите функцию, которая по названию города скажет, сколько там сейчас времени. Мы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *