Convert Unix Timestamp in C++ and Rust
Table of Contents
C++ and Rust both expose Unix time through their standard libraries, but the APIs are quite different. C++ has a legacy time_t from C plus the modern std::chrono from C++11. Rust has SystemTime in the standard library plus the popular chrono crate that adds parsing and formatting on top.
This guide covers both languages with the patterns you actually need in production code.
C++ Legacy time_t (Inherited From C)
The classic C/C++ way to handle Unix time is the time_t type from <ctime>. It works but the API is awkward and not thread-safe in places.
#include <ctime>
#include <iostream>
int main() {
// Current Unix timestamp
time_t now = time(nullptr);
std::cout << "Current: " << now << std::endl;
// Unix timestamp to struct tm (UTC)
time_t ts = 1711000000;
struct tm* utc = gmtime(&ts);
char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC", utc);
std::cout << buf << std::endl;
// Local time instead of UTC
struct tm* local = localtime(&ts);
// Date string back to time_t
struct tm tmStruct = {};
strptime("2024-03-21 07:46:40", "%Y-%m-%d %H:%M:%S", &tmStruct);
time_t parsed = timegm(&tmStruct); // GNU extension for UTC
return 0;
}
gmtime and localtime return pointers to a static buffer, which is not thread-safe. For multi-threaded code, use gmtime_r and localtime_r (POSIX) or gmtime_s and localtime_s (Windows).
C++ Modern chrono (C++11 and later)
std::chrono is the modern way. It is type-safe, thread-safe, and has explicit precision (seconds, milliseconds, microseconds, nanoseconds).
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
// Current Unix timestamp in seconds
auto now = system_clock::now();
auto seconds_since_epoch = duration_cast<seconds>(now.time_since_epoch()).count();
// In milliseconds, microseconds, nanoseconds
auto ms = duration_cast<milliseconds>(now.time_since_epoch()).count();
auto us = duration_cast<microseconds>(now.time_since_epoch()).count();
auto ns = duration_cast<nanoseconds>(now.time_since_epoch()).count();
// Unix seconds back to a time_point
auto tp = system_clock::from_time_t(1711000000);
// C++20 adds direct formatting
// std::format("{:%Y-%m-%d %H:%M:%S}", tp);
return 0;
}
Pre-C++20, formatting still requires going through time_t and strftime. C++20 adds std::format with chrono format specifiers, which is much cleaner if your compiler supports it.
For high-resolution measurement (durations rather than wall clock), use steady_clock instead of system_clock — it cannot be adjusted by NTP and is monotonic.
Rust SystemTime and chrono Crate
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
// Current Unix timestamp
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
println!("Seconds: {}", now.as_secs());
println!("Millis: {}", now.as_millis());
println!("Micros: {}", now.as_micros());
println!("Nanos: {}", now.as_nanos());
// From Unix seconds to SystemTime
let ts = 1711000000;
let time = UNIX_EPOCH + std::time::Duration::from_secs(ts);
}
The standard library SystemTime is enough for getting and storing Unix time. For formatting, parsing, or timezone work, you need the chrono crate:
// Cargo.toml: chrono = "0.4"
use chrono::{DateTime, Utc, TimeZone};
fn main() {
// Current Unix timestamp
let now = Utc::now().timestamp();
// From Unix seconds
let dt: DateTime<Utc> = Utc.timestamp_opt(1711000000, 0).unwrap();
println!("{}", dt.format("%Y-%m-%d %H:%M:%S"));
// In a specific timezone
use chrono_tz::America::New_York;
let ny_time = dt.with_timezone(&New_York);
}
The chrono crate is the de facto standard for date and time work in Rust. It handles Unix timestamp conversion, format strings (strftime-style), and timezones (with the chrono-tz companion crate for IANA names).
Rust gotcha: SystemTime can go backwards
duration_since(UNIX_EPOCH) returns a Result because the system clock can be set to before 1970 (in theory) or can move backwards on NTP adjustments. Production code should handle the error case rather than unwrapping.
For one-off conversions outside of code, the free Unix timestamp converter handles seconds and milliseconds.
Try It Free — No Signup Required
Runs 100% in your browser. No data is collected, stored, or sent anywhere.
Open Free Unix Timestamp ConverterFrequently Asked Questions
How do I get the current Unix timestamp in C++?
time(nullptr) from
Is gmtime thread-safe in C++?
No. gmtime and localtime return pointers to a static buffer, which is unsafe in multi-threaded code. Use gmtime_r and localtime_r on POSIX systems, or gmtime_s and localtime_s on Windows. The reentrant versions take a buffer you provide.
How do I convert a Unix timestamp in Rust?
Standard library: UNIX_EPOCH + Duration::from_secs(ts) gives a SystemTime. For formatting and timezones, use the chrono crate: Utc.timestamp_opt(ts, 0).unwrap() returns a DateTime
Should I use std::chrono or time_t in C++?
std::chrono for new code. It is type-safe (the compiler catches mixing seconds and milliseconds), thread-safe, and has explicit precision. time_t is fine for legacy code but error-prone. C++20 adds direct std::format support for chrono types, making it even more ergonomic.
What is the difference between system_clock and steady_clock in C++?
system_clock is the wall clock and represents Unix time. It can jump if the system clock is adjusted by NTP or by a user. steady_clock is monotonic — it only moves forward and is not affected by clock adjustments. Use steady_clock for measuring durations, system_clock for timestamps.
Why does Rust SystemTime return a Result?
Because the system clock can theoretically be set to a time before the Unix epoch, which would make duration_since return a negative duration — but Duration is unsigned in Rust. The Result lets you handle this case explicitly instead of panicking. Production code should use match or .unwrap_or instead of .unwrap.

