Calculating a Unix Epoch Date

Before you can embark upon the frightening topic of Time Math, you need to convert dates and times into Unix Epoch time_t values. It’s not that difficult of a task, assuming that you can accept that time programming in C isn’t complex and rude, which of course it is.

The function that returns a Unix Epoch value is mktime(). It eats a tm structure filled with the relevant date and time values. And therein lies the rub.

How can you fill in the tm structure? Here’s the definition of that structure from the man page:

int tm_sec;     /* seconds (0 - 60) */
int tm_min;     /* minutes (0 - 59) */
int tm_hour;    /* hours (0 - 23) */
int tm_mday;    /* day of month (1 - 31) */
int tm_mon;     /* month of year (0 - 11) */
int tm_year;    /* year - 1900 */
int tm_wday;    /* day of week (Sunday = 0) */
int tm_yday;    /* day of year (0 - 365) */
int tm_isdst;   /* is summer time in effect? */
char *tm_zone;  /* abbreviation of timezone name */
long tm_gmtoff; /* offset from UTC in seconds */

That information is coupled with the notice that the structure includes “at least” those fields. Yikes.

Filling that structure would take a lot of work, especially for the timezone string. But why do all that coding when you can have the computer do the work for you?

The localtime() function fills the tm structure. So you could pass localtime() the current time, after which it fills the tm structure. Then you could reset specific values within the tm structure, and finally call mktime() to retrieve the proper Unix Epoch, or time_t, value. The process is exactly what I’ve done in the sample code listed below.

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

int main()
{
    int month,day,year;
    struct tm *birthday;
    time_t bday,today;

    printf("Enter your birth month (1-12): ");
    scanf("%d",&month);
    printf("Enter your birth day: ");
    scanf("%d",&day);
    printf("Enter your birth year: ");
    scanf("%d",&year);

    time(&today);
    birthday = localtime(&today);
    birthday->tm_mon = month-1;
    birthday->tm_mday = day;
    birthday->tm_year = year-1900;

    bday = mktime(birthday);

    printf("You were born on %d/%d/%d\n",month,day,year);
    printf("That's Unix Epoch value %ld\n",bday);

    return(0);
}

The code begs the user to input a date, such as a birthdate although any specific date works. You could modify the code to input time values as well.

In Line 17, the time() function returns the current Unix Epoc value.

Line 18 fills the birthday tm structure with the current date and time information. To make the new Epoch value, you simply have to alter specific items in the structure. Lines 19, 20, and 21 do so for the month, day, and year.

In Line 19, the month must be reduced by one notch because the tm structure’s tm_mon value ranges from 0 through 11.

Also, in Line 21, the year value must be expressed as years since 1900, so that value needs to be subtracted from whatever year value was input.

Finally, at Line 23, the mktime() function translates the rebuilt tm structure birthday into a time_t value, bday.

Be aware that dates before January 1, 1970 appear as negative time_t values, so don’t think that the computer screwed up when you’re an old fart who was born before that date and you see a negative Epoch value!

Leave a Reply