Reputation: 1151
I have a struct that contains a timestamp. For that I am using the chrono library. There are two ways to get the timestamp:
DateTime::parse_from_str
which results in a DateTime<FixedOffset>
UTC::now
which results in a DateTime<UTC>
.Is there a way to convert DateTime<UTC>
to DateTime<FixedOffset>
?
Upvotes: 21
Views: 9055
Reputation: 3
If it was for the actual time you can do this.
https://docs.rs/chrono/latest/chrono/struct.Local.html#example-1
Upvotes: 0
Reputation: 11
because DateTime implements From<Utc> for DateTime<FixedOffset> you can simply call .into() to convert between the two:
let now_utc = Utc::now();
let now_fixed: DateTime<FixedOffset> = now_utc.into()
Upvotes: 0
Reputation: 16625
You can convert from a Local DateTime (FixedOffset, or TimeZoned) to UTC like this:
// Construct a Timezone object, we will use it later to build
// some DateTimes, but it is not strictly required for the
// conversion code
let tz_timezone = Tz::from_str(input_string_timezone)
.expect("failed to convert string to chrono tz");
// Create a DateTime::<Utc>
let utc_now = Utc::now();
println!("utc_now: {}", utc_now);
// Create a Local (Timezoned) DateTime
let naive_datetime = utc_now.naive_local();
let london_now = tz_timezone.from_local_datetime(&naive_datetime).unwrap();
println!("london_now: {}", london_now);
// Asside: We can do this another way too
let london_now = chrono_tz::Europe::London.from_local_datetime(&naive_datetime).unwrap();
println!("london_now: {}", london_now);
// The actual conversion code from local timezone time to UTC timezone time
let london_now_utc = Utc.from_utc_datetime(&london_now.naive_utc());
println!("london_now_utc: {}", london_now_utc);
// Bonus: calculate time difference
let difference_from_utc = london_now_utc - utc_now;
println!("difference_from_utc: {}", difference_from_utc);
You can also just use try_from
.
let fixed_offset_datetime: DateTime<chrono::FixedOffset> = ...
let utc_datetime = DateTime::<Utc>::try_from(fixed_offset_datetime)?;
Upvotes: 1
Reputation: 3149
Micheal's answer is not valid today. FixedOffset::east is deprecated as it might point to an out-of-bounds seconds space on the globe.
FixedOffset::east_opt is preferred today. It returns an Option<FixedOffset>
. It is None
if it points to out-of-bounds.
An example code:
Utc::now().with_timezone(&FixedOffset::east_opt(0).unwrap())
We can unwrap this safely (without the fear of panic) because zero seconds will never point to an out-of-bounds location.
Upvotes: 4
Reputation: 2209
You will want to do the following:
Utc::now().with_timezone(&FixedOffset::east(0))
You are basically converting Utc to FixedOffset with zero offset. Some of us complained about having a more obvious solution and a PR seems to be afoot.
Upvotes: 3
Reputation: 430671
I believe that you are looking for DateTime::with_timezone
:
use chrono::{DateTime, Local, TimeZone, Utc}; // 0.4.9
fn main() {
let now = Utc::now();
let then = Local
.datetime_from_str("Thu Jul 2 23:26:06 EDT 2015", "%a %h %d %H:%M:%S EDT %Y")
.unwrap();
println!("{}", now);
println!("{}", then);
let then_utc: DateTime<Utc> = then.with_timezone(&Utc);
println!("{}", then_utc);
}
I've added a redundant type annotation on then_utc
to show it is in UTC. This code prints
2019-10-02 15:18:52.247884539 UTC
2015-07-02 23:26:06 +00:00
2015-07-02 23:26:06 UTC
Upvotes: 22