Convert Unix Timestamp in C++

C++ provides multiple ways to handle time: the legacy C-style <ctime> library and the modern, type-safe <chrono> library introduced in C++11 and significantly enhanced in C++20.

Using C++11 <chrono> (Recommended)

The std::chrono library provides a precision-neutral, type-safe way to handle time.

C++ (C++11/17)
#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>

int main() {
    using namespace std::chrono;

    // 1. Get current Unix timestamp
    auto now = system_clock::now();
    
    // Convert to seconds (time_t)
    auto now_sec = duration_cast<seconds>(now.time_since_epoch()).count();
    std::cout << "Current timestamp (s): " << now_sec << std::endl;

    // Convert to milliseconds
    auto now_ms = duration_cast<milliseconds>(now.time_since_epoch()).count();
    std::cout << "Current timestamp (ms): " << now_ms << std::endl;

    // 2. Convert timestamp to Date string
    time_t timestamp = 1704067200; // 2024-01-01 00:00:00 UTC
    std::tm* tm_utc = std::gmtime(&timestamp);
    
    std::cout << "Date (UTC): " << std::put_time(tm_utc, "%Y-%m-%d %H:%M:%S") << std::endl;
    
    // 3. Convert timestamp to system_clock::time_point
    auto tp = system_clock::from_time_t(timestamp);
}

Using C++20 <chrono> (Modern)

C++20 adds calendar and timezone support, making date manipulation much easier and readable.

C++ (C++20)
#include <iostream>
#include <chrono>
#include <format> // Check compiler support

int main() {
    using namespace std::chrono;

    // Unix timestamp to year_month_day
    long long timestamp = 1704067200;
    auto tp = system_clock::time_point(seconds(timestamp));
    year_month_day ymd{floor<days>(tp)};
    
    std::cout << "Date: " << ymd << std::endl; // 2024-01-01

    // Detailed formatting (requires std::format support)
    // std::cout << std::format("{:%Y-%m-%d %H:%M:%S}", tp) << std::endl;
    
    // Timezone conversion (requires <chrono> timezone db support)
    /*
    auto zt_nyc = zoned_time{"America/New_York", tp};
    std::cout << "New York: " << zt_nyc << std::endl;
    */
}

Legacy <ctime> (C-Style)

Useful for interacting with C APIs or simpler use cases.

C++
#include <iostream>
#include <ctime>

int main() {
    // Current timestamp
    std::time_t result = std::time(nullptr);
    std::cout << "Current timestamp: " << result << std::endl;

    // Convert timestamp to string
    std::time_t timestamp = 1704067200;
    char buffer[80];
    
    // Use thread-safe versions if available
    struct tm time_info;
    
    #if defined(_WIN32) || defined(_WIN64)
        gmtime_s(&time_info, &timestamp); // Windows
    #else
        gmtime_r(&timestamp, &time_info); // POSIX/Linux/Mac
    #endif

    std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S UTC", &time_info);
    std::cout << buffer << std::endl;
}

Common Pitfalls

Year 2038 Problem

On 32-bit systems, time_t is often a signed 32-bit integer, which will overflow on January 19, 2038. Modern 64-bit systems typically use a 64-bit time_t, which is safe for billions of years. Check sizeof(time_t) to be sure.

Thread Safety of gmtime / localtime

Standard std::gmtime and std::localtime return a pointer to a static internal buffer. They are not thread-safe. Always use the reentrant versions: gmtime_r / localtime_r (POSIX) or gmtime_s / localtime_s (Windows).

std::chrono::system_clock Epoch

Before C++20, the epoch of system_clock was not strictly specified to be the Unix epoch (1970-01-01), though strictly all major implementations used it. C++20 standardized it to the Unix epoch.

Frequently Asked Questions

Should I use <ctime> or <chrono> in C++?

Use <chrono> (C++11 and later) for type safety, precision, and modern design. Use <ctime> only when interfacing with legacy C APIs or when a simple time_t is sufficient and precision is not a concern.

How do I get the current Unix timestamp in milliseconds?

Use std::chrono::system_clock::now() and cast the duration to milliseconds using std::chrono::duration_cast.

Is time_t susceptible to the Year 2038 problem?

It depends on the platform and compiler. On modern 64-bit systems, time_t is usually a 64-bit integer, avoiding the problem. On 32-bit systems, it is typically 32-bit and will overflow in 2038.

How do I format a timestamp in C++?

In C++20, use std::format or std::chrono::format. In C++11/14/17, convert the time_point to time_t and use std::put_time or strftime.