C Programming Time Handling Guide: Using time.h, strftime, and Preparing for the 2038 Problem

1. Introduction

C is a widely used programming language in system programming and embedded systems. Among its many applications, “working with time” is an essential element in numerous programs. For example, time handling is necessary in log systems that display the current time or in timer functions that execute specific processes at a designated time.

In this article, we will focus on the standard library time.h, which is used to handle time in C. By using this library, you can obtain the system’s current time, format and display it, and more. We will also touch on the well-known “Year 2038 Problem,” helping you learn the fundamental knowledge required to correctly implement time processing.

To make it easy for beginners to follow, we will explain step by step—from basic concepts to practical examples. By the end of this article, you will learn:

  • The essential knowledge required for time handling in C
  • How to retrieve and display the current time
  • How to format and manipulate time values
  • Common issues related to time handling and their solutions

By applying this knowledge, you will be able to implement effective time handling in various scenarios, such as logging, scheduling, and timers. In the next section, we’ll look into the fundamental data types and functions used for time handling in C.

2. Basic Knowledge for Handling Time in C

To handle time in C, you use the standard library time.h. This header file provides data types and functions for retrieving and manipulating system time. Here, we’ll go over the essential knowledge needed for time handling.

What is time.h?

The time.h library is the standard library in C for time-related operations. With this library, you can easily implement tasks such as retrieving the current system time, formatting time data, and performing addition or subtraction on time values.

The main data types and functions include:

  • Data types: time_t, struct tm
  • Functions: time(), localtime(), strftime(), and more

Key Data Types for Time Handling

To work with time in C, you need to understand the following data types.

1. time_t

time_t is a data type that represents system time. It stores the number of seconds elapsed since January 1, 1970, 00:00:00 (the Unix epoch). It is the fundamental type used when retrieving the current time in a program.

Example
#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL); // Get current time
    printf("Current time (in seconds): %ld\n", now);
    return 0;
}

This code prints the current system time in seconds.

2. struct tm

struct tm is a structure used to represent time in more detail. It stores information such as year, month, day, hour, minute, and second.

Structure Members

struct tm includes the following members:

  • tm_sec: Seconds (0–60)
  • tm_min: Minutes (0–59)
  • tm_hour: Hours (0–23)
  • tm_mday: Day of the month (1–31)
  • tm_mon: Month (0–11, where 0 = January)
  • tm_year: Years since 1900
  • tm_wday: Day of the week (0–6, where 0 = Sunday)
  • tm_yday: Day of the year (0–365)
  • tm_isdst: Daylight Saving Time (1 = in effect, 0 = not in effect, -1 = unknown)
Example
#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL);
    struct tm *local = localtime(&now); // Convert to local time

    printf("Current date and time: %d-%02d-%02d %02d:%02d:%02d\n",
           local->tm_year + 1900, // Year is relative to 1900
           local->tm_mon + 1,     // Month starts from 0
           local->tm_mday,
           local->tm_hour,
           local->tm_min,
           local->tm_sec);

    return 0;
}

This code displays the current date and time in the format “YYYY-MM-DD HH:MM:SS”.

Other Data Types for Time Measurement

1. clock_t

clock_t is a data type used to measure the execution time of a process. By combining it with the clock() function, you can measure how long code execution takes.

Example
#include <stdio.h>
#include <time.h>

int main() {
    clock_t start, end;
    double cpu_time_used;

    start = clock();
    // Code to be measured
    for (volatile long i = 0; i < 100000000; i++);
    end = clock();

    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("Execution time: %f seconds\n", cpu_time_used);

    return 0;
}

This code measures the execution time of a loop.

Summary of Data Types

The following table organizes the main data types used for time handling in C:

Data TypeDescriptionMain Usage
time_tHolds system time (elapsed seconds since epoch)Retrieve current time
struct tmHolds detailed time info (year, month, day, etc.)Formatting and manipulating time
clock_tHolds process execution timeMeasure execution duration

3. How to Get the Current Time

When retrieving the current time in C, you use the time() function provided by time.h. This section explains the basics, including how to convert to local time or UTC.

Getting the Current Time

The time() Function

The time() function returns the current system time as a time_t value. It is very simple to use—just pass NULL as the argument.

Example
#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL); // Get current time
    printf("Current time (in seconds): %ld\n", now);
    return 0;
}

Example Output

Current time (in seconds): 1700000000

Converting Time into Readable Format

Convert to Local Time: localtime()

The localtime() function converts a time_t value into a struct tm structure based on the system’s local time zone.

Example
#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL);
    struct tm *local = localtime(&now); // Convert to local time

    printf("Local time: %d-%02d-%02d %02d:%02d:%02d\n",
           local->tm_year + 1900,
           local->tm_mon + 1,
           local->tm_mday,
           local->tm_hour,
           local->tm_min,
           local->tm_sec);

    return 0;
}

Example Output

Local time: 2025-01-12 15:30:45

Convert to UTC: gmtime()

The gmtime() function converts a time_t value into a struct tm structure based on Coordinated Universal Time (UTC).

Example
#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL);
    struct tm *utc = gmtime(&now); // Convert to UTC

    printf("UTC time: %d-%02d-%02d %02d:%02d:%02d\n",
           utc->tm_year + 1900,
           utc->tm_mon + 1,
           utc->tm_mday,
           utc->tm_hour,
           utc->tm_min,
           utc->tm_sec);

    return 0;
}

Example Output

UTC time: 2025-01-12 06:30:45

Difference Between UTC and Local Time

  • UTC (Coordinated Universal Time): The world standard time, used as a reference for all time zones.
  • Local Time: Time adjusted according to the system’s time zone setting.

For example, Japan Standard Time (JST) is UTC+9 hours, so the output of localtime() and gmtime() will differ by 9 hours.

Displaying the Current Time as a String

The ctime() Function

The ctime() function directly converts a time_t value into a human-readable string.

Example
#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL);
    printf("Current time: %s", ctime(&now)); // Print as string
    return 0;
}

Example Output

Current time: Sat Jan 12 15:30:45 2025

Notes

  • The output is always in English.
  • For flexible formatting, use strftime() (explained in the next section).

4. Formatting Time with strftime()

If you want to display time in a human-readable format in C, the strftime() function lets you specify flexible formats. This function can output not only year, month, day, hours, minutes, and seconds, but also weekday names, day of the year, and more.

What is strftime()?

The strftime() function converts time data into a string based on a specified format using a struct tm.

Function Prototype

size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
  • s: Buffer to store the formatted string.
  • max: Maximum size of the buffer.
  • format: Format specifiers.
  • tm: The struct tm containing time data.

Return Value

The length (in bytes) of the resulting string. Returns 0 if an error occurs.

Basic Usage

Here’s an example that prints the current time in the format YYYY-MM-DD HH:MM:SS.

Example

#include <stdio.h>
#include <time.h>

int main() {
    time_t now = time(NULL);
    struct tm *local = localtime(&now);

    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local);

    printf("Formatted time: %s\n", buffer);
    return 0;
}

Example Output

Formatted time: 2025-01-12 15:30:45

Common Format Specifiers

SpecifierDescriptionExample
%YYear (4 digits)2025
%mMonth (01–12)01
%dDay (01–31)12
%HHour (00–23)15
%MMinute (00–59)30
%SSecond (00–60)45
%AWeekday (full)Saturday
%aWeekday (abbreviated)Sat
%jDay of year (001–366)012
%pAM/PM (locale-dependent)PM

Practical Examples

  • Japanese style date: "%Y年%m月%d日 %H時%M分%S秒"
  • Log timestamp: "%Y-%m-%d_%H-%M-%S"
  • English weekday format: "%a, %d %b %Y"

5. Adding and Subtracting Time

In C, you can calculate future or past times by adding or subtracting seconds from time_t values, or by using mktime().

Basic Concept

  • Addition: Add seconds to get a future time.
  • Subtraction: Subtract seconds to get a past time.

Example: 1 Hour Later

time_t now = time(NULL);
time_t future = now + (60 * 60);

Using mktime()

You can adjust dates (e.g., next day, next month) using mktime().

Example: Next Day

struct tm *local = localtime(&now);
local->tm_mday += 1;
time_t tomorrow = mktime(local);

Calculating Time Differences: difftime()

The difftime() function calculates the difference between two time_t values in seconds.

6. Preparing for the Year 2038 Problem

The time_t type may cause the well-known **Year 2038 Problem** if implemented as a signed 32-bit integer.

  • It counts seconds since the Unix epoch (Jan 1, 1970).
  • Max value: 2,147,483,647 seconds.
  • Overflow occurs on Jan 19, 2038, at 03:14:07 UTC.

Impact

  • Long-term timers and scheduling may fail.
  • File timestamps may be recorded incorrectly.
  • Authentication and logging systems may break.
  • Legacy embedded systems may be most affected.

Solutions

  • Migrate to 64-bit time_t (supports ~292 billion years).
  • Use libraries like Boost.DateTime or Chrono.
  • Redesign systems to store dates in other formats if necessary.

7. Practical Use Cases

C’s time handling can be applied to many real-world systems:

  • Logging: Add timestamps to logs.
  • Scheduling: Implement timer-based event execution.
  • Deadline management: Calculate due dates.
  • Performance measurement: Measure execution time.
  • Conditional logic: Change program behavior based on time.

8. Frequently Asked Questions (FAQ)

Q1. How do I get Japan Standard Time (JST)?

A. If your system time zone is set to JST, localtime() automatically returns JST.

Q2. Can I get time in milliseconds?

A. Not with time.h, but you can use platform-specific APIs such as gettimeofday() on UNIX.

Q3. How do I handle Daylight Saving Time (DST)?

A. Check tm_isdst in struct tm.

Q4. Can I display weekdays in Japanese?

A. Yes, with strftime() after calling setlocale(LC_TIME, "ja_JP.UTF-8");

Q5. How do I handle dates beyond 2038?

A. Use 64-bit time_t or alternative libraries. Most 64-bit environments already support it.

9. Conclusion

In this article, we explored **time handling in C**, from basics to advanced use:

  • Using time.h to retrieve and manipulate system time.
  • Formatting and displaying time with strftime().
  • Performing addition, subtraction, and difference calculations on time values.
  • Understanding and preparing for the **Year 2038 Problem**.
  • Applying time handling in real-world use cases such as logging, scheduling, and performance measurement.

Time handling is an essential feature for almost every program. By mastering these techniques, you can build more reliable and practical C applications.

侍エンジニア塾