My Rust application stores timestamps in UTC, but needs to output in the local timezone. The following code shows is trivial to do this:
use chrono::{DateTime, Local, Utc};
fn main() {
let utc = Utc::now();
utc_to_local(utc);
}
fn utc_to_local(utc: DateTime<Utc>) {
let local = DateTime::<Local>::from(utc);
println!("{}", utc.to_string());
println!("{}", local.to_string());
}
The output is as follows:
2021-08-26 14:55:31.590057252 UTC
2021-08-26 15:55:31.590057252 +01:00
However, I am not comfortable relying on environment settings like the local timezone in unit tests, and would like to test the formatting code (omitted here for simplicity) using a specific timezone or UTC. I am therefore trying to convert utc_to_local()
to a generic function:
use chrono::{DateTime, Local, TimeZone, Utc};
fn main() {
let utc = Utc::now();
utc_to_local::<Local>(utc);
}
fn utc_to_local<Tz: TimeZone>(utc: DateTime<Utc>) {
let local = DateTime::<Tz>::from(utc);
println!("{}", utc.to_string());
println!("{}", local.to_string());
}
This fails to compile:
error[E0308]: mismatched types
--> src/main.rs:9:38
|
8 | fn utc_to_local<Tz: TimeZone>(utc: DateTime<Utc>) {
| -- this type parameter
9 | let local = DateTime::<Tz>::from(utc);
| ^^^ expected type parameter `Tz`, found struct `Utc`
|
= note: expected struct `DateTime<Tz>`
found struct `DateTime<Utc>`
Can anyone tell me where I'm going wrong please?
UPDATE
Following advice in the post linked by Svetlin, this works:
use chrono::{DateTime, Local, TimeZone, Utc, Datelike, Timelike};
fn main() {
let utc = Utc::now();
utc_to_local(utc, Local);
}
fn utc_to_local<Tz: TimeZone>(utc: DateTime<Utc>, zone: Tz) {
let local = utc.with_timezone(&zone);
println!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", utc.year(), utc.month(), utc.day(), utc.hour(), utc.minute(), utc.second());
println!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", local.year(), local.month(), local.day(), local.hour(), local.minute(), local.second());
}
I had to do my own formatting instead of calling to_string()
, because I got a compiler error:
error[E0599]: the method `to_string` exists for struct `DateTime<Tz>`, but its trait bounds were not satisfied
--> src/main.rs:11:26
|
11 | println!("{}", local.to_string());
| ^^^^^^^^^ method cannot be called on `DateTime<Tz>` due to unsatisfied trait bounds
|
::: /home/hwalters/.cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.19/src/datetime.rs:70:1
|
70 | pub struct DateTime<Tz: TimeZone> {
| ---------------------------------
| |
| doesn't satisfy `DateTime<Tz>: ToString`
| doesn't satisfy `DateTime<Tz>: std::fmt::Display`
|
= note: the following trait bounds were not satisfied:
`DateTime<Tz>: std::fmt::Display`
which is required by `DateTime<Tz>: ToString`
But that's ok, I'm doing my own formatting anyway (that's the point of the unit test).