flashburn
flashburn

Reputation: 4508

convert number of days to a date in C using Jan 1 1990 as an epoch date

I have a variable which represents a date in number of days since Jan 1 1990. Does anybody know how I can do that? I'm working with MCS 8051, so I can't use any scripts, standard library functions or memory allocation (malloc or calloc). Also this is not a homework. Any help will be appreciated.

Upvotes: 4

Views: 2902

Answers (2)

Michał Górny
Michał Górny

Reputation: 19233

I'll give you a tip:

$ date --date 'jan 1 1990' +%s
631148400

This is the 'epoch date' of Jan 1 1990; expressed in seconds since the Unix epoch. Note this only valid for POSIX systems.


Now, that you made it clear that there are no standard library functions available, you'd probably want to use pre-calculated epoch time as a start and add days * 86400 to it.

Sadly, I guess that you will not have integer types large enough to handle that arithmetic. Since:

log(633826800, 2) = approx. 29.23951342

You'd need at least 32-bit type to hold the value of the Unix epoch itself.

For example, if you had a 32-bit uint32_t type, you could:

uint32_t days_to_epoch_date(int days)
{
    uint32_t ret = 631148400L; /* value for Jan 1 1990 */
    ret += 86400 * days;
    return ret;
}

If you need to use a different epoch or scale, the values will be different but the method will remain the same. Well, as long as the time measure is linear.


The following example is no longer correct with the new information but I'm leaving it in case anyone being able to use the standard library could find it.

For the code to be portable, you'd first want to assemble the epoch date in a struct tm:

#include <time.h>

time_t epoch_time_to_time_t(unsigned int days_since_epoch)
{
    struct tm t = {0};

    t.tm_mday = 1;
    t.tm_mon = 0; /* Jan */
    t.tm_year = 90; /* since 1900 */
    t.tm_isdst = -1;

    /* ... */
}

Then, as permitted by *7.23.2.3 The mktime function:

2 […] The original values of the tm_wday and tm_yday components of the structure are ignored, and the original values of the other components are not restricted to the ranges indicated above.

…add the number of days to the struct tm, and use mktime() to obtain the final time_t:

time_t epoch_time_to_time_t(unsigned int days_since_epoch)
{
    /* ... */

    t.tm_mday += days_since_epoch;

    return mktime(&t);
}

Upvotes: 2

RBerteig
RBerteig

Reputation: 43286

There is a book that collects a huge amount of date and time calculation details and algorithms, that is almost certainly worth checking out. It is supported by source code in standard C (probably C89, certainly not newer).

Standard C Date/Time Library: Programming the World's Calendars and Clocks by Lance Latham, CMP, 1998, ISBN 978-0879304966.

If you needed to start from scratch with date arithmetic, this would be a great resource if only because calenders are full of special cases that are easy to miss.

Upvotes: 1

Related Questions