๐ŸŽ“ A1Learner
๐Ÿ”

Rust Time Zones

A date and time mean one moment only when they are pinned to a place. chrono does this pinning with DateTime and a zone.

Pin a time to UTC

A NaiveDateTime floats free. and_utc() anchors it to UTC:

let naive = NaiveDate::from_ymd_opt(2026, 10, 22).unwrap().and_hms_opt(9, 0, 0).unwrap();
let utc = naive.and_utc();
println!("utc = {}", utc);

Show the same moment in Kolkata

India sits 5 hours 30 minutes east of UTC โ€” 19,800 seconds. with_timezone shows the same moment there:

let kolkata = FixedOffset::east_opt(5 * 3600 + 30 * 60).unwrap();
println!("in Kolkata = {}", utc.with_timezone(&kolkata));

West of UTC

West is the other direction. Four hours west, the same moment is still early morning:

let new_york = FixedOffset::west_opt(4 * 3600).unwrap();
println!("in New York = {}", utc.with_timezone(&new_york));

One number for the moment

timestamp() turns a DateTime into epoch seconds, and from_timestamp turns them back:

println!("timestamp = {}", utc.timestamp());
let back = DateTime::from_timestamp(utc.timestamp(), 0).unwrap();
println!("back again = {}", back);

The standard text shape

to_rfc3339() writes the moment in the shape APIs and log files agree on:

println!("rfc3339 = {}", utc.to_rfc3339());

Example

use chrono::{DateTime, FixedOffset, NaiveDate, Utc};

fn show(label: &str, moment: DateTime<Utc>, zone: FixedOffset) {
    let local = moment.with_timezone(&zone);
    println!("{}: {}", label, local.format("%H:%M on %A %d %B"));
}

fn main() {
    let call = NaiveDate::from_ymd_opt(2026, 10, 22)
        .unwrap()
        .and_hms_opt(9, 0, 0)
        .unwrap()
        .and_utc();

    println!("UTC: {}", call.format("%H:%M on %A %d %B"));
    show("Kolkata", call, FixedOffset::east_opt(5 * 3600 + 30 * 60).unwrap());
    show("New York", call, FixedOffset::west_opt(4 * 3600).unwrap());
    println!("timestamp = {}", call.timestamp());
}

Key points

  • DateTime<Utc> is a moment pinned to UTC, the world reference time with no offset
  • FixedOffset is a zone.
  • It sits a fixed number of seconds from UTC.
  • It sits east or west of it.
  • east_opt takes seconds east.
  • west_opt takes seconds west
  • A timestamp is a count of seconds.
  • It counts since the UNIX epoch (1 January 1970, UTC).
  • Every zone agrees on it.
  • That makes it the safe way.
  • Use it to store a moment.
  • Use it to send one
  • Fixed offsets never change.
  • Real places do: summer time moves the offset twice a year.
  • For named zones like Europe/London, the chrono-tz crate knows each place's rules and history

In this example, one video call is pinned to 09:00 UTC on Thursday 22 October 2026. The show function takes two things. It takes the moment and a fixed offset. with_timezone prints the same moment in that zone. It prints 14:30 in Kolkata. It prints 05:00 in New York. The date never changes here, because all three places are still inside the same day. The timestamp at the end is the single number every zone agrees on: 1792659600 seconds since the epoch.

Note

with_timezone changes how a moment is shown, never the moment itself โ€” the timestamp stays the same in every zone.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Rust Playground

Exercise

A call is pinned to 09:00 UTC. What time is it at a fixed offset of +05:30?