/******************************************************************************
Online C Compiler.
Code, Compile, Run and Debug C program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include <time.h>
/*---------------------------------------------------------------------------*/
// CCS code and wrappers needed to co-exist with standard C time.h stuff.
/*---------------------------------------------------------------------------*/
// Constants
// Define this to make the CCS routine return seconds since 1/1/2010.
#define TIME_T_USES_2010
#if defined(TIME_T_USES_2010)
#define SECOFFSET 1262304000 // 1/1/1970-1/1/2010 seconds.
#else
#define SECOFFSET 0
#endif
#define FALSE false
#define TRUE true
// Enums
typedef enum
{
SUNDAY = 0,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
} ccs_Weekday;
typedef enum
{
JANUARY = 0,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER
} ccs_Month;
// Typedefs/structures
typedef int32_t ccs_time_t;
typedef struct ccs_tm
{
uint8_t tm_sec; // seconds after the minute (0-59)
uint8_t tm_min; // minutes after the hour (0-59)
uint8_t tm_hour; // hours since midnight (0-23)
uint8_t tm_mday; // day of the month (1-31)
ccs_Month tm_mon; // month of the year (0-11)
uint16_t tm_year; // years since 1900
ccs_Weekday tm_wday; // day of the week (0-6) (Sunday=0)
uint16_t tm_yday; // day of the year (0-365)
} ccs_struct_tm;
// CCS time.c functions
/* Returns the number of days in a given month, leap year dependent
*/
static uint8_t ccs_DaysInMonth(uint8_t month, bool IsLeapYear)
{
switch(month)
{
case JANUARY:
case MARCH:
case MAY:
case JULY:
case AUGUST:
case OCTOBER:
case DECEMBER:
return 31;
case FEBRUARY:
if(IsLeapYear)
return 29;
return 28;
case APRIL:
case JUNE:
case SEPTEMBER:
case NOVEMBER:
return 30;
// error
default:
return 0;
}
}
/* Determines if a year is a leap year
* 'year' is the number of years since 1900
* A year is a leap year if is evenly divisible by 4 while not divisible by 100
* or if it is evenly divisible by 400. (Ex. 2000 is a leap year, 2100 is not)
* Returns TRUE if the year is a leap year, FALSE if not
*/
static bool ccs_LeapYear(uint16_t year)
{
if( ((year + 1900) % 400 == 0) ||
(((year + 1900) % 4 == 0) && ((year + 1900) % 100 != 0)) )
return TRUE;
return FALSE;
}
// see time.h for documentation
ccs_time_t ccs_mktime(ccs_struct_tm * timeT)
{
ccs_time_t unixTime = 0;
bool isLeapYear = FALSE;
uint16_t i = 0;
if(timeT != NULL)
{
unixTime += timeT->tm_sec;
unixTime += (uint32_t)(timeT->tm_min) * 60;
unixTime += (uint32_t)(timeT->tm_hour) * 3600;
isLeapYear = ccs_LeapYear(timeT->tm_year);
/* Clamp the month to [0,11) */
timeT->tm_mon %= 12;
for(i = 1;i <= timeT->tm_mon;i++)
{
unixTime += (ccs_DaysInMonth(i - 1,isLeapYear) * 86400);
}
/* Clamp the days in the month */
//timeT->tm_mday %= DaysInMonth(timeT->tm_mon,isLeapYear);
unixTime += (timeT->tm_mday - 1) * 86400;
if(isLeapYear)
{
timeT->tm_yday = (unixTime / 86400) % 366;
}
else
{
timeT->tm_yday = (unixTime / 86400) % 365;
}
#if defined(TIME_T_USES_2010)
i = 110;
#else
i = 70;
#endif
while(i < timeT->tm_year)
{
isLeapYear = ccs_LeapYear(i);
if(isLeapYear)
{
unixTime += (31622400); // seconds in 366 days
}
else
{
unixTime += (31536000); // seconds in 365 days
}
i++;
}
#if defined(TIME_T_USES_2010)
timeT->tm_wday = ((unixTime / 86400) + 5) % 7;
#else
timeT->tm_wday = ((unixTime / 86400) + 4) % 7;
#endif
}
return unixTime;
}
// Test code.
int main()
{
// 31,536,000 seconds in a year.
// 86,400 seconds in a day
// 31,622,400 seconds in a leap year.
printf (" 31536000 seconds in a year.\n"
" 86400 seconds in a day\n"
" 31622400 seconds in a leap year.\n"
"1729810550 seconds since 1/1/1970\n");
// Standard C
time_t rawtime;
struct tm * ptm;
time ( &rawtime );
ptm = gmtime ( &rawtime );
printf ("STD: %04u-%02u-%02u %02u:%02u:%02u is %10"PRIu32" seconds since 1/1/1970\r\n",
ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
rawtime);
printf ("STD: %04u-%02u-%02u %02u:%02u:%02u is %10"PRIu32" seconds since 1/1/2010\r\n",
ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
rawtime - 1262304000);
// CCS
ccs_time_t unixTime;
ccs_struct_tm nTime;
nTime.tm_year = ptm->tm_year; // years since 1900
nTime.tm_mon = ptm->tm_mon; // months since January (0-11)
nTime.tm_mday = ptm->tm_mday; // day of the month (1-31)
nTime.tm_hour = ptm->tm_hour; // hours since midnight (0-23)
nTime.tm_min = ptm->tm_min; // minutes after the hour (0-59)
nTime.tm_sec = ptm->tm_sec; // seconds after the minute (0-61) leap second!
nTime.tm_wday = ptm->tm_wday; // days since Sunday
nTime.tm_yday = ptm->tm_yday; // days since January 1
unixTime = ccs_mktime (&nTime);
printf ("CCS: %04u-%02u-%02u %02u:%02u:%02u is %10"PRIu32" seconds since 1/1/1970\r\n",
nTime.tm_year + 1900, nTime.tm_mon + 1, nTime.tm_mday,
nTime.tm_hour, nTime.tm_min, nTime.tm_sec,
unixTime + SECOFFSET);
#if defined(TIME_T_USES_2010)
printf ("CCS: %04u-%02u-%02u %02u:%02u:%02u is %10"PRIu32" seconds since 1/1/2010\r\n",
nTime.tm_year + 1900, nTime.tm_mon + 1, nTime.tm_mday,
nTime.tm_hour, nTime.tm_min, nTime.tm_sec,
unixTime);
#endif
return 0;
}