-2

I am trying to convert a chrono_tz::Tz timezone offset into a fixed offset in units of number of hours.

This is how I have managed to construct a Tz object:

let input_string_timezone = "Europe/London";

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

From this I am able to get the name of the offset, as well as the offset in units of seconds, for when daylight savings is in effect and not in effect. This is how I did that:

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());

I have managed to convert the timezone object into an offset in terms of the number of seconds from UTC. However, what I have produced is two possible values of the offset, rather than the current value of the offset, today.

What I wish to do is obtain "todays" offset. In order to do this I would have to supply todays date, to some trait or function, but I don't know if the Rust chrono or chrono_tz crates have support for this operation.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225

2 Answers2

0

You might want to check on the documentation of dst_offset() again (emphasis mine) it gives

The additional offset from UTC that is currently in effect; typically for daylight saving time

So a complete function getting todays offset from UTC for a time zone is this:

/*
[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()
}

You can confirm that it really gives the current offset by adding a couple of months to now for example with .checked_add_months(chrono::Months::new(6)).unwrap()

cafce25
  • 15,907
  • 4
  • 25
  • 31
0

The problem can be solved by finding the difference between a UTC datetime and a local datetime.

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);
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225