Search code examples
ctimeunix-timestampdata-conversion

Unix Time stamp creation in C from custom data fields


I wish to create a Unix time stamp. I have a micro-controller with a ble connection that I send the present time to via a GATT connection. I receive the data several integers.

These are Year, Month, Day, Hour, Minute and Second. e.g:

  • Year = 2020, month = 3, day = 9, hour = 10, minute = 10, second = 10.

I want to convert this to Unix time so I can then increment the value every second via a interrupt based timer. Therefore, what is the correct way to conjoin this data together to form the Unix time. My presumption is as follows:

Create a integer value large enough to store the value called unix time and add the equivalent seconds from the respective time components(year,month etc).

These are the value in seconds

  • Year_in_seconds = 31,556,952
  • Month_in_seconds = 2,630,000
  • Day_in_seconds = 86,400
  • Hour_in_seconds = 3,600
  • Minute_in_seconds = 60

Therefore, Unix time =

  • (nYears * Year_in_seconds)+(nMonths * Month_in_seconds)+(nDays * Days_in_seconds)+(nHours * Hour_in_seconds)+(nMinutes * Minute_in_seconds)+(nSeconds * 1)

Is there anything wrong about my presumptions here?

I don't know how unix time deals with the different number of days in a month as different months have different lengths. Also leap years. So do I need another lookup table or something to make this accurate?

Or what is the correct method for getting the unix time from my set of data?


Solution

  • This should be accurate up to 2100:

    unsigned int tounix (int year, int month, int day, int hour, int min, int sec) {
        unsigned int epoch = 0;
        // These are the number of days in the year up to the corresponding month
        static const unsigned int monthdays[] = { 0, 31, 59, 90, 120, 151, 181, 211, 242, 272, 303, 333 };
        epoch = (year-1970)*86400*365u +    // Account the years
                ((year-1968)/4)*86400 +    // leap years
                monthdays[month-1]*86400 + // days in past full month
                (day-1)*86400u + hour*3600 + min*60 + sec; // days, hours, mins, secs
    
        if (!(year%4)&&month < 3) // Correct 1 day if in leap year before Feb-29
            epoch -= 86400;
    
        return epoch;
    }
    

    Input is expected as:

    • Year: 1970 - 2099
    • Month: 1 - 12
    • Day: 1 - 31
    • Hour, Minute, Second: as usual ;)