Try it yourself with our free Epoch Converter tool — runs entirely in your browser, no signup needed.

How to Convert Unix timestamps in C++

How to convert Unix timestamps in C++

Converting Unix timestamps to human-readable dates is a common task in many C++ applications. A Unix timestamp is a 32-bit integer representing the number of seconds that have elapsed since January 1, 1970, at 00:00:00 UTC. This article provides a comprehensive guide on how to convert Unix timestamps in C++.

Quick Example

#include <ctime>
#include <iostream>

int main() {
    time_t unix_timestamp = 1643723400; // example Unix timestamp
    struct tm* time_info;
    time_info = gmtime(&unix_timestamp);
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info);
    std::cout << buffer << std::endl;
    return 0;
}

This code converts the Unix timestamp 1643723400 to a human-readable date string in the format YYYY-MM-DD HH:MM:SS.

Step-by-Step Breakdown

Here's a line-by-line explanation of the code:

  • time_t unix_timestamp = 1643723400;: We define a time_t variable unix_timestamp and assign it a value of 1643723400, which is an example Unix timestamp.
  • struct tm* time_info;: We declare a pointer to a struct tm object called time_info. The struct tm object is used to store the broken-down time.
  • time_info = gmtime(&unix_timestamp);: We pass the address of unix_timestamp to the gmtime() function, which converts the Unix timestamp to a struct tm object in UTC time zone. The result is stored in time_info.
  • char buffer[80];: We declare a character array buffer with a size of 80 to store the formatted date string.
  • strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info);: We use the strftime() function to format the date stored in time_info into a string. The format string is "%Y-%m-%d %H:%M:%S", which corresponds to the format YYYY-MM-DD HH:MM:SS. The formatted string is stored in buffer.
  • std::cout << buffer << std::endl;: Finally, we print the formatted date string to the console.

Handling Edge Cases

Here are a few common edge cases to consider:

Empty/Null Input

#include <stdexcept>

int main() {
    time_t unix_timestamp = 0; // empty input
    try {
        struct tm* time_info = gmtime(&unix_timestamp);
        if (time_info == nullptr) {
            throw std::invalid_argument("Invalid input");
        }
        // ...
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
}

In this example, we check if gmtime() returns a null pointer, indicating an invalid input.

Invalid Input

#include <stdexcept>

int main() {
    time_t unix_timestamp = -1; // invalid input
    try {
        struct tm* time_info = gmtime(&unix_timestamp);
        if (time_info == nullptr) {
            throw std::invalid_argument("Invalid input");
        }
        // ...
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
}

In this example, we check if gmtime() returns a null pointer, indicating an invalid input.

Large Input

#include <climits>

int main() {
    time_t unix_timestamp = LLONG_MAX; // large input
    try {
        struct tm* time_info = gmtime(&unix_timestamp);
        if (time_info == nullptr) {
            throw std::overflow_error("Input too large");
        }
        // ...
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
}

In this example, we check if gmtime() returns a null pointer, indicating an overflow error.

Unicode/Special Characters

#include <locale>
#include <codecvt>

int main() {
    time_t unix_timestamp = 1643723400; // example Unix timestamp
    struct tm* time_info = gmtime(&unix_timestamp);
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info);
    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
    std::wstring wide_string = converter.from_bytes(buffer);
    std::wcout << wide_string << std::endl;
}

In this example, we convert the formatted date string to a wide string using std::wstring_convert and std::codecvt_utf8, and then print it to the console using std::wcout.

Common Mistakes

Here are a few common mistakes developers make when converting Unix timestamps in C++:

Mistake 1: Not Checking for Null Pointers

// Wrong
struct tm* time_info = gmtime(&unix_timestamp);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info);

// Correct
struct tm* time_info = gmtime(&unix_timestamp);
if (time_info == nullptr) {
    throw std::invalid_argument("Invalid input");
}
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info);

Mistake 2: Not Handling Overflow Errors

// Wrong
time_t unix_timestamp = LLONG_MAX;
struct tm* time_info = gmtime(&unix_timestamp);

// Correct
time_t unix_timestamp = LLONG_MAX;
try {
    struct tm* time_info = gmtime(&unix_timestamp);
    if (time_info == nullptr) {
        throw std::overflow_error("Input too large");
    }
    // ...
} catch (const std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
    return 1;
}

Mistake 3: Not Using Thread-Safe Functions

// Wrong
struct tm* time_info = localtime(&unix_timestamp);

// Correct
struct tm* time_info = localtime_r(&unix_timestamp, &time_info);

Note that localtime_r is a thread-safe version of localtime.

Performance Tips

Here are a few performance tips for converting Unix timestamps in C++:

Tip 1: Use gmtime_r Instead of gmtime

// Slow
struct tm* time_info = gmtime(&unix_timestamp);

// Fast
struct tm time_info;
gmtime_r(&unix_timestamp, &time_info);

gmtime_r is a reentrant version of gmtime that avoids the overhead of thread-safety.

Tip 2: Avoid Using strftime with Complex Format Strings

// Slow
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %A %B %d, %Y", time_info);

// Fast
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info);

Complex format strings can slow down strftime. If possible, use simpler format strings.

Tip 3: Use std::put_time Instead of strftime

// Slow
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info);

// Fast
std::time_t t = mktime(time_info);
std::cout << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S") << std::endl;

std::put_time is a more modern and efficient way to format dates.

FAQ

Q: What is the range of valid Unix timestamps?

A: The range of valid Unix timestamps is from January 1, 1970, to January 19, 2038.

Q: How do I convert a Unix timestamp to a specific time zone?

A: You can use the localtime function to convert a Unix timestamp to the local time zone.

Q: How do I handle daylight saving time (DST) when converting Unix timestamps?

A: You can use the localtime function to handle DST.

Q: What is the difference between gmtime and localtime?

A: gmtime converts a Unix timestamp to UTC time, while localtime converts a Unix timestamp to the local time zone.

Q: How do I format a date string to include the day of the week?

A: You can use the %A format specifier in strftime to include the day of the week.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp