Skip to Content
Course content

132: Formatting Time with strftime

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I remember a junior dev on my team a few years back who spent an entire afternoon scratching his head because his log timestamps were coming up empty. He had the logic right, he was calling the functions in the right order, but the output was just... nothing. Here is a snippet of the code he showed me:

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

int main() {
    time_t rawtime = time(NULL);
    struct tm *timeinfo = localtime(&rawtime);
    char buffer[10]; 

    // He wanted "2023-10-25 14:30:05"
    strftime(buffer, 10, "%Y-%m-%d %H:%M:%S", timeinfo);
    
    printf("Current time: %s\n", buffer);
    return 0;
}

The Silent Failure of Small Buffers

The problem here is subtle because the code doesn't crash. It doesn't segfault, and it doesn't throw a warning. It just fails silently. He allocated 10 bytes for buffer, but the format string "%Y-%m-%d %H:%M:%S" requires about 20 characters (including the null terminator).

In C, strftime is actually safer than sprintf because it takes the maximum size of the buffer as an argument. However, if the resulting string—including the null terminator—exceeds that size, strftime doesn't just truncate the string; it returns 0 and leaves the contents of the buffer in an undefined state (usually empty or partially filled). Because he wasn't checking the return value, he had no idea the function was failing.

Giving the String Room to Breathe

The first thing we did was give the buffer a reasonable size. Unless you are working in an extremely memory-constrained embedded system, there's no reason to be stingy with a few bytes for a timestamp. A buffer of 64 or 128 is usually plenty. I also taught him to check the return value. If strftime returns 0, it means your buffer was too small.

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

int main() {
    time_t rawtime = time(NULL);
    struct tm *timeinfo = localtime(&rawtime);
    char buffer[64]; // Plenty of space now

    if (strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeinfo) == 0) {
        fprintf(stderr, "Buffer too small for the requested format\n");
        return 1;
    }
    
    printf("Current time: %s\n", buffer);
    return 0;
}

Picking the Right Specifiers

Once we got the string to actually appear, we realized he was mixing up his case. In strftime, case matters immensely. It's not like printf where %d is always an integer. Here, %Y (uppercase) gives you the full year (2023), while %y (lowercase) gives you the two-digit year (23).

I usually keep a cheat sheet for these, but here are the ones you'll actually use 90% of the time:

  • %Y: Year with century (e.g., 2023)
  • %m: Month as a decimal number (01-12)
  • %d: Day of the month (01-31)
  • %H: Hour in 24h format (00-23)
  • %M: Minute (00-59)
  • %S: Second (00-59)
  • %A: Full weekday name (e.g., Wednesday)
  • %B: Full month name (e.g., October)

One thing to watch out for: strftime is locale-dependent. If your program runs on a machine set to a French locale, %A will output "mercredi" instead of "Wednesday". If you need a consistent format regardless of where the code is running, stick to the numeric specifiers like %Y-%m-%d.




📋 Practical Task

Build a Custom Audit Log Timestamp Generator

Write a C program that mimics a professional audit log entry. Your program should:

  1. Get the current system time.
  2. Use strftime to format the time into a string that looks exactly like this: [Wednesday, October 25, 2023 | 14:30:05].
  3. Ensure you use a buffer large enough to hold this long string and include a check to verify that strftime succeeded.
  4. Print the resulting timestamp followed by a dummy log message, like: [Wednesday, October 25, 2023 | 14:30:05] USER_LOGIN: User 'admin' logged in from 192.168.1.1.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.