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?