buster
buster

Reputation: 1151

How to convert DateTime<UTC> to DateTime<FixedOffset> or vice versa?

I have a struct that contains a timestamp. For that I am using the chrono library. There are two ways to get the timestamp:

  1. Parsed from a string via DateTime::parse_from_str which results in a DateTime<FixedOffset>
  2. The current time, received by UTC::now which results in a DateTime<UTC>.

Is there a way to convert DateTime<UTC> to DateTime<FixedOffset>?

Upvotes: 21

Views: 9055

Answers (6)

Soy_Asher
Soy_Asher

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

Andrei Amatuni
Andrei Amatuni

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

user2138149
user2138149

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

Eray Erdin
Eray Erdin

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

Michael K Madison
Michael K Madison

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

Shepmaster
Shepmaster

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

Related Questions