int day_number (int year, int month) { int Yfirst,Mfirst,Dfirst; int y,m; y=m=0; for(Yfirst=1582;Yfirst<year;Yfirst++) { y=y+365+leap_year(Yfirst); } for(Mfirst=1;Mfirst<month;Mfirst++) { if(Mfirst==1) { m=m+31; } else if(Mfirst==2) { m=m+28+leap_year(year); } else if(Mfirst==3) { m=m+31; } else if(Mfirst==4) { m=m+30; } else if(Mfirst==5) { m=m+31; } else if(Mfirst==6) { m=m+30; } else if(Mfirst==7) { m=m+31; } else if(Mfirst==8) { m=m+31; } else if(Mfirst==9) { m=m+30; } else if(Mfirst==10) { m=m+31; } else if(Mfirst==11) { m=m+30; } else if(Mfirst==12) { m=m+31; } } return m+y; }
/****************************************************************************** * @brief Calculate the day, month, year and seconds given a Fractional * Julian Day. * @return dmy stucture. * @note if calendar="standard" or "gregorian" (default), Julian day follows * Julian Calendar on and before 1582-10-5, Gregorian calendar after * 1582-10-15. * * if calendar="proleptic_gregorian", Julian Day follows gregorian * calendar. * * if calendar="julian", Julian Day follows julian calendar. * * Algorithm: * Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). * Willmann-Bell, Virginia. p. 63 * * based on redate.py by David Finlayson. *****************************************************************************/ void dmy_julian_day(double julian, unsigned short int calendar, dmy_struct *dmy) { double day, F, eps; int second; int Z, alpha; int A, B, C, D, E; int nday, dayofyr; int year, month; bool is_leap; if (julian < 0) { log_err("Julian Day must be positive"); } // get the day (Z) and the fraction of the day (F) // add 0.000005 which is 452 ms in case of jd being after // second 23:59:59 of a day we want to round to the next day Z = (int) round(julian); F = (double) (julian + 0.5 - Z); if (calendar == CALENDAR_STANDARD || calendar == CALENDAR_GREGORIAN) { alpha = (int) ((((double) Z - 1867216.0) - 0.25) / 36524.25); A = Z + 1 + alpha - (int) (0.25 * (double) alpha); // check if dates before oct 5th 1582 are in the array if (julian < 2299160.5) { A = Z; } } else if (calendar == CALENDAR_PROLEPTIC_GREGORIAN) { alpha = (int) (((Z - 1867216.0) - 0.25) / 36524.25); A = Z + 1 + alpha - (int) (0.25 * alpha); } else if (calendar == CALENDAR_JULIAN) { A = Z; } else { log_err("unknown calendar, must be one of julian,standard,gregorian," "proleptic_gregorian"); } B = A + 1524; C = (int) (6680. + (((double) B - 2439870.) - 122.1) / (double) DAYS_PER_JYEAR); D = (int) (DAYS_PER_YEAR * C + (int) (0.25 * (double) C)); E = (int) (((double) (B - D)) / 30.6001); // Convert to date day = floor(B - D - floor(30.6001 * (double) E) + F); if (day < 1) { day = 1; } nday = B - D - 123; dayofyr = nday - 305; if (nday <= 305) { dayofyr = nday + 60; } month = E - 1; if (month > MONTHS_PER_YEAR) { month -= MONTHS_PER_YEAR; } year = C - 4715; if (month > 2) { year -= 1; } if (year <= 0) { year -= 1; } // a leap year? is_leap = leap_year(year, calendar); if (is_leap && (month > 2)) { dayofyr += 1; } eps = max(DBL_EPSILON, DBL_EPSILON * julian); second = (int) round((double) F * (double) SEC_PER_DAY - eps); if (second < 0) { second = 0.; } dmy->day = (int) day; dmy->day_in_year = dayofyr; dmy->month = month; dmy->year = year; dmy->dayseconds = second; return; }
/*--------------------------------------------------------------------------*/ IsotimeEpoch _convert2epoch(long year, long month, long day, long hh, long mm, long ss, double uuuuuu, long osign, long Hh, long Mm, long Ss) { long days, base; IsotimeEpoch epoch; if (ISOTIME_debug>0) fprintf(stderr,"_convert2epoch BEGIN\n"); epoch.offset = (long int) 0; epoch.fract = (double) 0.0; epoch.sec = (long int) 0; epoch.status = -1; days = year*365+leap_days(year) - DAYS_19700101; switch (month) { case 1: days+=day; break; case 2: days+=day+31; break; case 3: days+=day+59; break; case 4: days+=day+90; break; case 5: days+=day+120; break; case 6: days+=day+151; break; case 7: days+=day+181; break; case 8: days+=day+212; break; case 9: days+=day+243; break; case 10: days+=day+273; break; case 11: days+=day+304; break; case 12: days+=day+334; break; default : month=0; // invalid } if ( month ) { // correct march to december leap years if ( leap_year ( year ) ) { if (month>2) days+=1; } epoch.offset = osign*( (Hh*60+Mm)*60+Ss ); base = floor(uuuuuu); epoch.fract = uuuuuu - (double) base; epoch.sec = ((days*24+hh)*60+mm)*60+ss+base-epoch.offset; // normalize fract and sec base = floor(epoch.fract); epoch.fract -= (double) base; epoch.sec += base; epoch.status = 0; // success } if (ISOTIME_debug>2) fprintf(stderr," %ld (DAYS_%04ld%02ld%02ld) - %ld (DAYS_19700101) = %ld\n", days+DAYS_19700101,year,month,day,DAYS_19700101,days); if (ISOTIME_debug>0) fprintf(stderr,"_convert2epoch END\n"); return ( epoch ); } // _convert2epoch
/*+++------------------------------------------------------------------------ NAME epoch2isotime --- convert IsotimeEpoch to isotime string SYNOPSIS const char * epoch2isotime( char buffer[], size_t buflen, IsotimeEpoch epoch ) DESCRIPTION (not implemented) RETURN VALUE pointer to isotime string in buffer ----------------------------------------------------------------------------*/ const char * epoch2isotime( char buffer[], size_t buflen, IsotimeEpoch epoch ) { char epobuf[EPOLEN]; char osign_c; long year=0, month=0, day=0; long hh=0, mm=0, ss=0; double fract=0.0; long Hh=0, Mm=0, Ss=0; long days, yd, ts, tz, leap; long base; if (ISOTIME_debug>0) fprintf(stderr,"epoch2isotime %s BEGIN\n", epoch2string( epobuf, EPOLEN, epoch ) ); if ( (!buffer)||(buflen<ISOLEN) ) { if (ISOTIME_debug>0) fprintf(stderr,"epoch2isotime END\n"); return ( ( const char *) NULL ); } buffer[0] ='\0'; if (!epoch.status) { // normalize fract and sec base = floor(epoch.fract); epoch.fract -= (double) base; epoch.sec += base; // convert2time fract = epoch.fract; if (epoch.offset<0) osign_c='-'; else osign_c='+'; tz = epoch.offset; Hh = floor(tz/3600); tz -= Hh*3600; Mm = floor(tz/60); tz -= Mm*60; Ss = tz; Hh=labs(Hh); Mm=labs(Mm); Ss = labs(Ss); if (ISOTIME_debug>3) fprintf(stderr," osign=%c1, Hh=%ld, Mm=%ld, Ss=%ld\n",osign_c,Hh,Mm,Ss); ts = epoch.sec + epoch.offset; // add time zone offset days = floor( ts/3600/24 ); ts -= days*3600*24; if (ts<0) { days-=1; ts+=3600*24; } hh = floor(ts/3600); ts -= hh*3600; mm = floor(ts/60); ts -= mm*60; ss = ts; days += DAYS_19700101; // == year*365+leap_days year = floor( days/365 ); yd = days - year*365 - leap_days( year ); // day in the year if (ISOTIME_debug>3) fprintf(stderr," hh=%ld, hm=%ld, ss=%ld\n",hh,mm,ss); // days contains all leap_days => year is correct or too high while ( yd <= 0 ) { year--; yd = days - year*365 - leap_days( year ); // day in the year } if (ISOTIME_debug>3) fprintf(stderr," year=%ld, yd=%ld\n",year,yd); // get number of leap days in the year if ( leap_year ( year ) ) leap=1; else leap=0; if (yd<=31) { month= 1; day=yd; } // Jan else if (yd<=59+leap) { month= 2; day=yd-31; } // Feb else if (yd<=90+leap) { month= 3; day=yd-59-leap; } // Mar else if (yd<=120+leap) { month= 4; day=yd-90-leap; } // Apr else if (yd<=151+leap) { month= 5; day=yd-120-leap; } // May else if (yd<=181+leap) { month= 6; day=yd-151-leap; } // Jun else if (yd<=212+leap) { month= 7; day=yd-181-leap; } // Jul else if (yd<=243+leap) { month= 8; day=yd-212-leap; } // Aug else if (yd<=273+leap) { month= 9; day=yd-243-leap; } // Sep else if (yd<=304+leap) { month=10; day=yd-273-leap; } // Oct else if (yd<=334+leap) { month=11; day=yd-304-leap; } // Nov else { month=12; day=yd-334-leap; } // Dec // print switch (ISOTIME_mode) { case IsotimeModeSpace: sprintf(buffer,"%04ld-%02ld-%02ld %02ld:%02ld:%02ld.%06ld %c%02ld%02ld", year,month,day,hh,mm,ss,(long) floor(epoch.fract*1e6+0.5), osign_c,labs(Hh),labs(Mm) ); break; default: // IsotimeModeNoSpace sprintf(buffer,"%04ld-%02ld-%02ldT%02ld:%02ld:%02ld.%06ld%c%02ld%02ld", year,month,day,hh,mm,ss,(long) floor(epoch.fract*1e6+0.5), osign_c,labs(Hh),labs(Mm) ); } } if (ISOTIME_debug>0) fprintf(stderr,"epoch2isotime %s END\n",buffer); return( buffer ); } // epoch2isotime
int Date::current_dpm() const { if (leap_year() && mth == ly_month) return months[mth] + leap_days; return months[mth]; }
int main(int argc, char **argv) { struct tm *local_time; time_t now; int ch, day, month, year, yflag; char *progname, *p; int num_months = NUM_MONTHS; progname = argv[0]; if ((p = strrchr(progname, '/')) != NULL) progname = p+1; __progname = progname; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW) || defined(HAVE_LIBTERMCAP) if ((term = getenv("TERM"))) { int ret; my_setupterm(term, 1, &ret); if (ret > 0) { Senter = my_tgetstr("so","smso"); Sexit = my_tgetstr("se","rmso"); Slen = strlen(Senter) + strlen(Sexit); } } #endif /* * The traditional Unix cal utility starts the week at Sunday, * while ISO 8601 starts at Monday. We read the start day from * the locale database, which can be overridden with the * -s (Sunday) or -m (Monday) options. */ #if HAVE_DECL__NL_TIME_WEEK_1STDAY /* * You need to use 2 locale variables to get the first day of the week. * This is needed to support first_weekday=2 and first_workday=1 for * the rare case where working days span across 2 weeks. * This shell script shows the combinations and calculations involved: for LANG in en_US ru_RU fr_FR csb_PL POSIX; do printf "%s:\t%s + %s -1 = " $LANG $(locale week-1stday first_weekday) date -d"$(locale week-1stday) +$(($(locale first_weekday)-1))day" +%w done en_US: 19971130 + 1 -1 = 0 #0 = sunday ru_RU: 19971130 + 2 -1 = 1 fr_FR: 19971201 + 1 -1 = 1 csb_PL: 19971201 + 2 -1 = 2 POSIX: 19971201 + 7 -1 = 0 */ { int wfd; union { unsigned int word; char *string; } val; val.string = nl_langinfo(_NL_TIME_WEEK_1STDAY); wfd = val.word; wfd = day_in_week(wfd % 100, (wfd / 100) % 100, wfd / (100 * 100)); weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7; } #endif yflag = 0; while ((ch = getopt(argc, argv, "13mjsyV")) != -1) switch(ch) { case '1': num_months = 1; /* default */ break; case '3': num_months = 3; break; case 's': weekstart = 0; /* default */ break; case 'm': weekstart = 1; break; case 'j': julian = 1; break; case 'y': yflag = 1; break; case 'V': printf(_("%s from %s\n"), progname, PACKAGE_STRING); return 0; case '?': default: usage(); } argc -= optind; argv += optind; time(&now); local_time = localtime(&now); day = month = year = 0; switch(argc) { case 3: if ((day = atoi(*argv++)) < 1 || day > 31) errx(1, _("illegal day value: use 1-%d"), 31); /* FALLTHROUGH */ case 2: if ((month = atoi(*argv++)) < 1 || month > 12) errx(1, _("illegal month value: use 1-12")); /* FALLTHROUGH */ case 1: if ((year = atoi(*argv)) < 1 || year > 9999) errx(1, _("illegal year value: use 1-9999")); if (day) { int dm = days_in_month[leap_year(year)][month]; if (day > dm) errx(1, _("illegal day value: use 1-%d"), dm); day = day_in_year(day, month, year); } else if ((local_time->tm_year + 1900) == year) { day = local_time->tm_yday + 1; } if (!month) yflag=1; break; case 0: day = local_time->tm_yday + 1; year = local_time->tm_year + 1900; month = local_time->tm_mon + 1; break; default: usage(); } headers_init(); if (!isatty(1)) day = 0; /* don't highlight */ if (yflag && julian) j_yearly(day, year); else if (yflag) yearly(day, year); else if (num_months == 1) monthly(day, month, year); else if (num_months == 3) monthly3(day, month, year); exit(0); }
long conv_str_date ( const char *string, int flags, int format, int order) { static char *month_name [] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; static byte month_days [] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, order_ptr [][3] = /* Year, Month, Day pointers */ { /* for various orders & formats */ /* YY MM DD YYYY MM DD YY MM YYYY MM MM DD */ { 0, 2, 4 }, { 0, 4, 6 }, { 0, 2, 99 }, { 0, 4, 99 }, { 99, 0, 2 }, { 4, 2, 0 }, { 4, 2, 0 }, { 2, 0, 99 }, { 2, 0, 99 }, { 99, 2, 0 }, { 4, 0, 2 }, { 4, 0, 2 }, { 2, 0, 99 }, { 2, 0, 99 }, { 99, 0, 2 }, }; char date_digits [9], /* 8 digits of date */ month_letters [4] = "???", /* 3 characters of month */ ch; /* Next character in date */ long feedback; /* Returned date; -1 = error */ int digits, /* Number of digits in string */ delimiters, /* Number of delimiters in date */ digitseq, /* Number of digits in sequence */ count, /* Number of month letters */ year, /* Date year value */ month, /* Date month value */ day, /* Date day value */ order_index, /* Index into order table */ y_ptr, /* Where is year in date? */ m_ptr, /* Where is month in date? */ d_ptr, /* Where is day in date? */ date_order = order; /* Actual date order */ Bool had_month; /* Did we already get a month? */ ASSERT (format >= DATE_FORMAT_FIRST && format <= DATE_FORMAT_LAST); ASSERT (order >= DATE_ORDER_FIRST && order <= DATE_ORDER_LAST); conv_reason = 0; /* No conversion errors so far */ if (flags & FLAG_D_ORDER_YMD) date_order = DATE_ORDER_YMD; else if (flags & FLAG_D_ORDER_DMY) date_order = DATE_ORDER_DMY; else if (flags & FLAG_D_ORDER_MDY) date_order = DATE_ORDER_MDY; /* Collect date digits */ digits = 0; /* Nothing collected so far */ digitseq = 0; /* No digits in sequence */ feedback = 0; /* No errors so far */ delimiters = 0; /* We allow up to 2 delimiters */ had_month = FALSE; /* True after 3-letter month seen */ do { ch = *string++; if (isdigit (ch)) { if (digits < 8) { digitseq++; date_digits [digits++] = ch; } else { conv_reason = CONV_ERR_DATE_SIZE; feedback = -1; /* Too many digits */ } } else { /* Fill-up to even number of digits */ if (digits > (digits / 2) * 2) { date_digits [digits] = date_digits [digits - 1]; date_digits [digits - 1] = '0'; digits++; } /* 3 or 5 in a row is not allowed */ if (digitseq == 3 || digitseq == 5) { conv_reason = CONV_ERR_REJECT_3_5; feedback = -1; } digitseq = 0; /* If a letter, try to match against a month */ if (isalpha (ch)) { if (had_month) { conv_reason = CONV_ERR_MULTIPLE_MONTH; feedback = -1; } else { for (count = 0; isalpha (ch); ) { if (count < 3) month_letters [count++] = (char) tolower (ch); ch = *string++; } string--; /* Move back to char after month */ if (count < 3) { conv_reason = CONV_ERR_BAD_MONTH; feedback = -1; /* Too few letters */ } month_letters [3] = 0; for (count = 0; count < 12; count++) if (streq (month_letters, month_name [count])) { count++; date_digits [digits++] = (char) (count / 10 + '0'); date_digits [digits++] = (char) (count % 10 + '0'); had_month = TRUE; break; } if (!had_month) { conv_reason = CONV_ERR_BAD_MONTH; feedback = -1; /* Month not found */ } } } else if (ispunct (ch)) /* Skip any delimiter */ if ((++delimiters > 2) || (format > DATE_YMD_LAST && delimiters > 1)) { conv_reason = CONV_ERR_MULTIPLE_DELIM; feedback = -1; /* Multiple delimiters */ } } } until (ch == 0); /* Return zero date if empty */ if (digits == 0) return (feedback); /* Calculate offset in date_digits for various date order & formats */ order_index = (date_order - 1) * 5; /* Each row has 5 items */ if (format <= DATE_YMD_LAST) { if (digits == 6) ; /* nothing */ else if (digits == 8) order_index += 1; } else if (format <= DATE_YM_LAST) { date_digits [digits++] = '0'; date_digits [digits++] = '0'; if (digits == 6) order_index += 2; else if (digits == 8) order_index += 3; else { conv_reason = CONV_ERR_DATE_SIZE; return (-1); /* Error - bad date size */ } } else if (format <= DATE_MD_LAST) { date_digits [digits++] = '0'; date_digits [digits++] = '0'; if (digits == 6) order_index += 4; else { conv_reason = CONV_ERR_DATE_SIZE; return (-1); /* Error - bad date size */ } } /* Decode order to pick-up offset of day/month/year in date_digits */ y_ptr = order_ptr [order_index][0]; m_ptr = order_ptr [order_index][1]; d_ptr = order_ptr [order_index][2]; # define DIGIT(x) (date_digits [(x)] - '0') if (y_ptr != 99) { year = DIGIT (y_ptr) * 10 + DIGIT (y_ptr + 1); if (digits == 8) year = DIGIT (y_ptr + 2) * 10 + DIGIT (y_ptr + 3) + year * 100; if (year < 50) year += 2000; else if (year < 100) year += 1900; } else year = 0; if (m_ptr != 99) { month = DIGIT (m_ptr) * 10 + DIGIT (m_ptr + 1); if (month == 0 || month > 12) { conv_reason = CONV_ERR_OUT_OF_RANGE; feedback = -1; } } else month = 0; if (d_ptr != 99) { day = DIGIT (d_ptr) * 10 + DIGIT (d_ptr + 1); if ((day == 0 || day > (int) month_days [month - 1]) || (month == 2 && day == 29 && !leap_year (year))) { conv_reason = CONV_ERR_OUT_OF_RANGE; feedback = -1; } } else day = 0; if (feedback == 0) feedback = year * 10000L + month * 100 + day; return (feedback); }
struct tm64* localtime64_r(const time64_t* time64, struct tm64* tm64) { if(*time64 >= LONG_MIN && *time64 <= LONG_MAX) { struct tm tm; memset(&tm, 0, sizeof(tm)); time_t time = (time_t) *time64; if(localtime_r(&time, &tm)) { tm_to_tm64(&tm, tm64); #ifndef HAVE_TM_ZONE #if HAVE_TZNAME && HAVE_DAYLIGHT tm64->tm_zone = tzname[daylight && tm64->tm_isdst]; #else tm64->tm_zone = NULL; #endif #endif return tm64; } } /* * First determine the (approximate) year that this timestamp * is in using the gmtime64_r function. We then use this so * we are able to map this to a year that should be compatible * with the system localtime_r */ struct tm64 gm; gmtime64_r(time64, &gm); int64_t gm_year = gm.tm_year; if(gm_year < 1902) { /* For years below the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(gm_year, gm.tm_mon, gm.tm_mday); if(gm.tm_mon == 2 && leap_year(gm_year)) { gm.tm_year = lower_leap_month_table[day]; } else { gm.tm_year = lower_common_month_table[gm.tm_mon][day]; } } else if(gm_year > 2037) { /* For years above the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(gm_year, gm.tm_mon, gm.tm_mday); if(gm.tm_mon == 2 && leap_year(gm_year)) { gm.tm_year = higher_leap_month_table[day]; } else { gm.tm_year = higher_common_month_table[gm.tm_mon][day]; } } /* * Get the timestamp for the safe date that we mapped the * large date to. */ time_t time = (time_t)timegm64(&gm); struct tm tm; memset(&tm, 0, sizeof(tm)); localtime_r(&time, &tm); tm_to_tm64(&tm, tm64); tm64->tm_year = gm_year; /* * We need to correct here for the case where the timezone difference * results in the dates occuring in two different years. */ int month_diff = tm64->tm_mon - gm.tm_mon; if(month_diff == 11) { tm64->tm_year--; } else if(month_diff == -11) { tm64->tm_year++; } /* If the gm year is a leap year, but the local isn't and we're on * December 31st in the local year, this is marked as day 365 because * the gm year is a leap year. Therefore we need to substract 1. */ if(!leap_year(tm64->tm_year) && tm64->tm_yday == 365 ) { tm64->tm_yday--; } #ifndef HAVE_TM_ZONE #if HAVE_TZNAME && HAVE_DAYLIGHT tm64->tm_zone = tzname[daylight && tm64->tm_isdst]; #else tm64->tm_zone = NULL; #endif #endif return tm64; }
struct tm64* gmtime64_r(const time64_t* time64, struct tm64* tm64) { if(*time64 >= LONG_MIN && *time64 <= LONG_MAX) { struct tm tm; memset(&tm, 0, sizeof(tm)); time_t time = (time_t) *time64; if(gmtime_r(&time, &tm)) { tm_to_tm64(&tm, tm64); return tm64; } } tm64->tm_isdst = 0; tm64->tm_gmtoff = 0; tm64->tm_zone = (char *)"UTC"; /* * Fallback because out of range of time_t or gmtime_r failed */ int64_t year = 1970; int leap = 0; time64_t days = *time64; tm64->tm_sec = (int)(days % 60); days /= 60; tm64->tm_min = (int)(days % 60); days /= 60; tm64->tm_hour = (int)(days % 24); days /= 24; WRAP (tm64->tm_sec, tm64->tm_min, 60); WRAP (tm64->tm_min, tm64->tm_hour, 60); WRAP (tm64->tm_hour, days, 24); /* * days now contains the number of days that have passed. * Week day is easy since we know the day that the epoch occured */ tm64->tm_wday = (int)((days + 4) % 7); if (tm64->tm_wday < 0) { tm64->tm_wday += 7; } if (days >= 0) { /* Gregorian cycles */ int64_t cycles = days / DAYS_IN_GREGORIAN_CYCLE; if(cycles) { days -= cycles * DAYS_IN_GREGORIAN_CYCLE; year += cycles * 400; } leap = leap_year(year); while (days >= length_of_year[leap]) { days -= length_of_year[leap]; ++year; leap = leap_year(year); } tm64->tm_mon = 0; while (days >= days_in_month[leap][tm64->tm_mon]) { days -= days_in_month[leap][tm64->tm_mon]; tm64->tm_mon++; } } else { --year; int64_t cycles = days / DAYS_IN_GREGORIAN_CYCLE + 1; if(cycles) { days -= cycles * DAYS_IN_GREGORIAN_CYCLE; year += cycles * 400; } leap = leap_year(year); while (days < -length_of_year[leap]) { days += length_of_year[leap]; year--; leap = leap_year(year); } /* Months */ tm64->tm_mon = 11; while (days < -days_in_month[leap][tm64->tm_mon]) { days += days_in_month[leap][tm64->tm_mon]; tm64->tm_mon--; } days += days_in_month[leap][tm64->tm_mon]; } tm64->tm_year = year; /* Remaining days are the day of the month, +1 since we don't * count with offset 0 for days */ tm64->tm_mday = (int) days + 1; tm64->tm_yday = julian_days_by_month[leap][tm64->tm_mon] + (int)days; return tm64; }