18

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>?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
buster
  • 1,071
  • 1
  • 10
  • 15
  • You really should be including some amount of example code. As it is right now, any answerer needs to create some arbitrary amount of code that uses the chrono crate which may or may not match the code you have. Please read about creating an [MCVE](/help/mcve). – Shepmaster Jul 03 '15 at 03:33

4 Answers4

19

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
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Thanks! Sorry, i didn't post sample code but yours actually solves my problem. I didn't see that and i was trying to figure out by the API docs... Now that i see it, it seems obvious. – buster Jul 03 '15 at 08:32
  • Great example! However, this does not handle `DateTime` (which of course is a distinct type from `Utc` and `Local`). – JamesThomasMoon Jul 25 '22 at 22:22
3

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.

Michael K Madison
  • 2,242
  • 3
  • 21
  • 35
1

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.

Eray Erdin
  • 2,633
  • 1
  • 32
  • 66
0

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