Как преобразовать вариант перечисления TimeZone в фиксированное смещение?

Я пытаюсь преобразоватьchrono_tz::Tzсмещение часового пояса в фиксированное смещение в единицах количества часов.

Вот как мне удалось создать объект Tz:

      let input_string_timezone = "Europe/London";

let tz_timezone = Tz::from_str(input_string_timezone)
    .expect("failed to convert string to chrono tz");

Отсюда я могу получить имя смещения, а также смещение в секундах, когда летнее время действует, а когда не действует. Вот как я это сделал:

      println!("tz_offset: {}", tz_offset);
println!("tz_offset base_utc_offset: {}", tz_offset.base_utc_offset());
println!("tz_offset dst_offset: {}", tz_offset.dst_offset());

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

Я хочу получить смещение «сегодня». Чтобы сделать это, мне пришлось бы указать сегодняшнюю дату для какой-то черты или функции, но я не знаю, будет ли Rustchronoилиchrono_tzящики имеют поддержку этой операции.

2 ответа

Проблему можно решить, найдя разницу между датой и временем в формате UTC и локальной датой и временем.

      let input_string_timezone = "Europe/London";

let tz_timezone = Tz::from_str(input_string_timezone)
    .expect("failed to convert string to chrono tz");

// First create a UTC datetime
let utc_now = Utc::now();
println!("utc_now: {}", utc_now);

// From this we need the naive datetime
let naive_date_now = utc_now.date_naive();
println!("naive_date_now: {}", naive_date_now);

// Using the naive datetime, we can construct a datetime, in the 
// timezone of our choosing. In this case, I have used the previously
// obtained timezone object for Europe/London
let london_now = tz_timezone.from_local_datetime(&naive_datetime).unwrap();
println!("london_now: {}", london_now);

// Note that rather than constructing a timezone object from a string
// we can also select the timezone type from the module of our choice
let london_now = chrono_tz::Europe::London.from_local_datetime(&naive_datetime).unwrap();
println!("london_now: {}", london_now);

// We need to convert this to UTC
let london_now_utc = Utc.from_utc_datetime(&london_now.naive_utc());
println!("london_now_utc: {}", london_now_utc);

// Finally, we can subtract to obtain a Duration
let difference_from_utc = london_now_utc - utc_now;
println!("difference_from_utc: {}", difference_from_utc);

Возможно, вы захотите проверить документацию dst_offset()опять же (выделено мной) это дает

Дополнительное смещение от UTC, действующее в данный момент ; обычно для летнего времени

Итак, полная функция получения сегодняшнего смещения от UTC для часового пояса такова:

      /*
[dependencies]
chrono = "*"
chrono-tz = "*"
*/
use chrono::TimeZone;
use chrono_tz::OffsetComponents;
fn get_todays_offset(tz: chrono_tz::Tz) -> chrono::Duration {
    let now = chrono::Utc::now().naive_utc();
    let offset = tz.offset_from_utc_datetime(&now);
    offset.base_utc_offset() + offset.dst_offset()
}

Вы можете убедиться, что он действительно дает текущее смещение, добавив пару месяцев кnowнапример с.checked_add_months(chrono::Months::new(6)).unwrap()

Другие вопросы по тегам