Exemplo n.º 1
0
struct tm *gmtime_r(const time_t *timep, struct tm *r) {
  time_t i;
  register time_t work=*timep%(SPD);
  r->tm_sec=work%60; work/=60;
  r->tm_min=work%60; r->tm_hour=work/60;
  work=*timep/(SPD);
  r->tm_wday=(4+work)%7;
  for (i=1970; ; ++i) {
    register time_t k=__isleap(i)?366:365;
    if (work>=k)
      work-=k;
    else
      break;
  }
  r->tm_year=i-1900;
  r->tm_yday=work;

  r->tm_mday=1;
  if (__isleap(i) && (work>58)) {
    if (work==59) r->tm_mday=2; /* 29.2. */
    work-=1;
  }

  for (i=11; i && (__spm[i]>work); --i) ;
  r->tm_mon=i;
  r->tm_mday+=work-__spm[i];
  return r;
}
Exemplo n.º 2
0
void rtctime_gmtime (const int32 stamp, struct rtc_tm *r)
{
  int32_t i;
  int32_t work = stamp % (SPD);
  r->tm_sec = work % 60; work /= 60;
  r->tm_min = work % 60; r->tm_hour = work / 60;
  work = stamp / (SPD);
  r->tm_wday = (4 + work) % 7;
  for (i = 1970; ; ++i) {
    int32_t k = __isleap (i) ? 366 : 365;
    if (work >= k) {
      work -= k;
    } else {
      break;
    }
  }
  r->tm_year = i - 1900;
  r->tm_yday = work;

  r->tm_mday = 1;
  if (__isleap (i) && (work > 58)) {
    if (work == 59) r->tm_mday = 2; /* 29.2. */
    work -= 1;
  }

  for (i = 11; i && (__spm[i] > work); --i) ;
  r->tm_mon = i;
  r->tm_mday += work - __spm[i];
}
Exemplo n.º 3
0
/* Compute the `struct tm' representation of *T,
   offset OFFSET seconds east of UTC,
   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
   Return nonzero if successful.  */
int
__offtime (const time_t *t, long int offset, struct tm *tp)
{
  time_t days, rem, y;
  const unsigned short int *ip;

  days = *t / SECS_PER_DAY;
  rem = *t % SECS_PER_DAY;
  rem += offset;
  while (rem < 0)
    {
      rem += SECS_PER_DAY;
      --days;
    }
  while (rem >= SECS_PER_DAY)
    {
      rem -= SECS_PER_DAY;
      ++days;
    }
  tp->tm_hour = rem / SECS_PER_HOUR;
  rem %= SECS_PER_HOUR;
  tp->tm_min = rem / 60;
  tp->tm_sec = rem % 60;
  /* January 1, 1970 was a Thursday.  */
  tp->tm_wday = (4 + days) % 7;
  if (tp->tm_wday < 0)
    tp->tm_wday += 7;
  y = 1970;

#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))

  while (days < 0 || days >= (__isleap (y) ? 366 : 365))
    {
      /* Guess a corrected year, assuming 365 days per year.  */
      time_t yg = y + days / 365 - (days % 365 < 0);

      /* Adjust DAYS and Y to match the guessed year.  */
      days -= ((yg - y) * 365
	       + LEAPS_THRU_END_OF (yg - 1)
	       - LEAPS_THRU_END_OF (y - 1));
      y = yg;
    }
  tp->tm_year = y - 1900;
  if (tp->tm_year != y - 1900)
    {
      /* The year cannot be represented due to overflow.  */
      __set_errno (EOVERFLOW);
      return 0;
    }
  tp->tm_yday = days;
  ip = __mon_yday[__isleap(y)];
  for (y = 11; days < (long int) ip[y]; --y)
    continue;
  days -= ip[y];
  tp->tm_mon = y;
  tp->tm_mday = days + 1;
  return 1;
}
Exemplo n.º 4
0
/**
 * Convert UNIX timestamp to date/time
 * Based on code from GNU C Library
 */
void date_from_timestamp(uint32_t timestamp, DateTimeT *date_time)
{
	uint16_t y;
	int16_t days;
	uint32_t rem;

	days = timestamp / SECS_PER_DAY;
	rem = timestamp % SECS_PER_DAY;
	while (rem < 0)
	{
		rem += SECS_PER_DAY;
		--days;
	}
	while (rem >= SECS_PER_DAY)
	{
		rem -= SECS_PER_DAY;
		++days;
	}
	date_time->hour = rem / SECS_PER_HOUR;
	rem %= SECS_PER_HOUR;
	date_time->min = rem / 60;
	date_time->sec = rem % 60;
	/* January 1, 1970 was a Thursday.  */
	date_time->wday = (4 + days) % 7;
	if (date_time->wday < 0){
		date_time->wday += 7;
	}
	y = 1970;

#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))

	while (days < 0 || days >= (__isleap (y) ? 366 : 365))
	{
		/* Guess a corrected year, assuming 365 days per year.  */
		uint16_t yg = y + days / 365 - (days % 365 < 0);

		/* Adjust DAYS and Y to match the guessed year.  */
		days -= ((yg - y) * 365
				 + LEAPS_THRU_END_OF (yg - 1)
				 - LEAPS_THRU_END_OF (y - 1));
		y = yg;
	}
	date_time->year = y - 1900;
	if (date_time->year != y - 1900)
	{
		/* The year cannot be represented due to overflow.  */
		return;
	}
	const uint16_t *ip = __mon_yday[__isleap(y)];
	for (y = 11; days < (uint16_t)ip[y]; --y){
		continue;
	}
	days -= ip[y];
	date_time->mon = y;
	date_time->mday = days + 1;
}
Exemplo n.º 5
0
s32 dev_rtc_date_to_days(struct DATE Dt, u32 *days)
{
	u32 i;
	u32 j;

	if((Dt.year<YEAR_STA) || (Dt.year>year_LAST))
	{
		return -1;
	}
	if((Dt.mon>12) || (Dt.mon == 0) || (0 == Dt.day))
	{
		return -1;
	}
	if(__isleap(Dt.year))
	{
		if(Dt.day>Month_day_Max_L[Dt.mon])
		{
			return -1;
		}
	} 
	else
	{
		if(Dt.day>Month_day_Max_C[Dt.mon])
		{
			return -1;
		}
	}
	//计算年---->天
	j = 0;
	for(i=YEAR_STA; i<Dt.year; i++)
	{
		if(__isleap(i))
		{
			//闰年
			j += 366;
		}
		else
		{
			j += 365;
		}
	}
	//计算月转天
	if(__isleap(Dt.year))
	{	//闰年LeapYear
		j += Month_day_Accu_L[Dt.mon-1];
	}
	else
	{
		j += Month_day_Accu_C[Dt.mon-1];
	}
	//天
	*days = j+(Dt.day-1);
	return 0;
}
Exemplo n.º 6
0
/* Compute the `struct tm' representation of *T,
   offset OFFSET seconds east of UTC,
   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
   Return nonzero if successful.  */
int
offtime (unsigned long t, efi_time_t *tp)
{
	const unsigned short int __mon_yday[2][13] =
	{
		/* Normal years.  */
		{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
		/* Leap years.  */
		{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
	};
	long int days, rem, y;
	const unsigned short int *ip;

	days = t / SECS_PER_DAY;
	rem = t % SECS_PER_DAY;
	while (rem < 0) {
		rem += SECS_PER_DAY;
		--days;
	}
	while (rem >= SECS_PER_DAY) {
		rem -= SECS_PER_DAY;
		++days;
	}
	tp->hour = rem / SECS_PER_HOUR;
	rem %= SECS_PER_HOUR;
	tp->minute = rem / 60;
	tp->second = rem % 60;
	/* January 1, 1970 was a Thursday.  */
	y = 1970;

#	define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#	define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
#	define __isleap(year) \
	  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))

	while (days < 0 || days >= (__isleap (y) ? 366 : 365)) {
		/* Guess a corrected year, assuming 365 days per year.  */
		long int yg = y + days / 365 - (days % 365 < 0);

		/* Adjust DAYS and Y to match the guessed year.  */
		days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)
			 - LEAPS_THRU_END_OF (y - 1));
		y = yg;
	}
	tp->year = y;
	ip = __mon_yday[__isleap(y)];
	for (y = 11; days < (long int) ip[y]; --y)
		continue;
	days -= ip[y];
	tp->month = y + 1;
	tp->day = days + 1;
	return 1;
}
Exemplo n.º 7
0
Arquivo: time.c Projeto: Xilinx/xen
struct tm gmtime(unsigned long t)
{
    struct tm tbuf;
    long days, rem;
    int y;
    const unsigned short int *ip;

    y = 1970;
#if BITS_PER_LONG >= 64
    /* Allow the concept of time before 1970.  64-bit only; for 32-bit
     * time after 2038 seems more important than time before 1970. */
    while ( t & (1UL<<39) )
    {
        y -= 400;
        t += ((unsigned long)(365 * 303 + 366 * 97)) * SECS_PER_DAY;
    }
    t &= (1UL << 40) - 1;
#endif

    days = t / SECS_PER_DAY;
    rem = t % SECS_PER_DAY;

    tbuf.tm_hour = rem / SECS_PER_HOUR;
    rem %= SECS_PER_HOUR;
    tbuf.tm_min = rem / 60;
    tbuf.tm_sec = rem % 60;
    /* January 1, 1970 was a Thursday.  */
    tbuf.tm_wday = (4 + days) % 7;
    if ( tbuf.tm_wday < 0 )
        tbuf.tm_wday += 7;
    while ( days >= (rem = __isleap(y) ? 366 : 365) )
    {
        ++y;
        days -= rem;
    }
    while ( days < 0 )
    {
        --y;
        days += __isleap(y) ? 366 : 365;
    }
    tbuf.tm_year = y - 1900;
    tbuf.tm_yday = days;
    ip = (const unsigned short int *)__mon_lengths[__isleap(y)];
    for ( y = 0; days >= ip[y]; ++y )
        days -= ip[y];
    tbuf.tm_mon = y;
    tbuf.tm_mday = days + 1;
    tbuf.tm_isdst = -1;

    return tbuf;
}
Exemplo n.º 8
0
/**
 * time64_to_tm - converts the calendar time to local broken-down time
 *
 * @totalsecs	the number of seconds elapsed since 00:00:00 on January 1, 1970,
 *		Coordinated Universal Time (UTC).
 * @offset	offset seconds adding to totalsecs.
 * @result	pointer to struct tm variable to receive broken-down time
 */
void time64_to_tm(time64_t totalsecs, int offset, struct tm *result)
{
	long days, rem, y;
	int remainder;
	const unsigned short *ip;

	days = div_s64_rem(totalsecs, SECS_PER_DAY, &remainder);
	rem = remainder;
	rem += offset;
	while (rem < 0) {
		rem += SECS_PER_DAY;
		--days;
	}
	while (rem >= SECS_PER_DAY) {
		rem -= SECS_PER_DAY;
		++days;
	}

	result->tm_hour = rem / SECS_PER_HOUR;
	rem %= SECS_PER_HOUR;
	result->tm_min = rem / 60;
	result->tm_sec = rem % 60;

	/* January 1, 1970 was a Thursday. */
	result->tm_wday = (4 + days) % 7;
	if (result->tm_wday < 0)
		result->tm_wday += 7;

	y = 1970;

	while (days < 0 || days >= (__isleap(y) ? 366 : 365)) {
		/* Guess a corrected year, assuming 365 days per year. */
		long yg = y + math_div(days, 365);

		/* Adjust DAYS and Y to match the guessed year. */
		days -= (yg - y) * 365 + leaps_between(y, yg);
		y = yg;
	}

	result->tm_year = y - 1900;

	result->tm_yday = days;

	ip = __mon_yday[__isleap(y)];
	for (y = 11; days < ip[y]; y--)
		continue;
	days -= ip[y];

	result->tm_mon = y;
	result->tm_mday = days + 1;
}
Exemplo n.º 9
0
void __tm_conv(struct tm *tmbuf, time_t * pt, long offset)
{
	register int y;
	long days;		/* This breaks but not for a while 8) */
	long rem;
	unsigned char *ip;

	days = *pt / SECS_PER_DAY;
	rem = *pt % SECS_PER_DAY;
	rem += offset;

	while (rem < 0) {
		rem += SECS_PER_DAY;
		--days;
	}
	/* FIXME: speed - we should probably do some of this with ifs and
	   powers of 2 down as a trade against size */
	while (rem >= SECS_PER_DAY) {
		rem -= SECS_PER_DAY;
		++days;
	}
	tmbuf->tm_hour = rem / SECS_PER_HOUR;
	rem %= SECS_PER_HOUR;
	tmbuf->tm_min = rem / 60;
	tmbuf->tm_sec = rem % 60;

	/* January 1, 1970 was a Thursday.  */
	tmbuf->tm_wday = (4 + days) % 7;
	if (tmbuf->tm_wday < 0)
		tmbuf->tm_wday += 7;
	y = 1970;
	while (days >= (rem = __isleap(y) ? 366 : 365)) {
		++y;
		days -= rem;
	}
	while (days < 0) {
		--y;
		days += __isleap(y) ? 366 : 365;
	}
	tmbuf->tm_year = y - 1900;
	tmbuf->tm_yday = days;
	ip = __mon_lengths[__isleap(y)];
	y = 0;
	while (days >= ip[y])
		days -= ip[y++];
	tmbuf->tm_mon = y;
	tmbuf->tm_mday = days + 1;
	/* Until we do DST flagging */
	tmbuf->tm_isdst = 0;
}
Exemplo n.º 10
0
time_t timegm(struct tm *const t) {
  register time_t  day;
  register time_t  i;
  register time_t years = t->tm_year - 70;

  if (t->tm_sec>60) { t->tm_min += t->tm_sec/60; t->tm_sec%=60; }
  if (t->tm_min>60) { t->tm_hour += t->tm_min/60; t->tm_min%=60; }
  if (t->tm_hour>24) { t->tm_mday += t->tm_hour/24; t->tm_hour%=24; }
  if (t->tm_mon>12) { t->tm_year += t->tm_mon/12; t->tm_mon%=12; }
  while (t->tm_mday>__spm[1+t->tm_mon]) {
    if (t->tm_mon==1 && __isleap(t->tm_year+1900)) {
      --t->tm_mday;
    }
    t->tm_mday-=__spm[t->tm_mon];
    ++t->tm_mon;
    if (t->tm_mon>11) { t->tm_mon=0; ++t->tm_year; }
  }

  if (t->tm_year < 70)
    return (time_t) -1;

  /* Days since 1970 is 365 * number of years + number of leap years since 1970 */
  day  = years * 365 + (years + 1) / 4;

  /* After 2100 we have to substract 3 leap years for every 400 years
     This is not intuitive. Most mktime implementations do not support
     dates after 2059, anyway, so we might leave this out for it's
     bloat. */
  if ((years -= 131) >= 0) {
    years /= 100;
    day -= (years >> 2) * 3 + 1;
    if ((years &= 3) == 3) years--;
    day -= years;
  }
Exemplo n.º 11
0
/* Returns 1 if MDAY is a valid day of the month in month MON of year
   YEAR, and 0 if it is not.  */
static int
check_mday (int year, int mon, int mday)
{
  switch (mon)
    {
    case 0:
    case 2:
    case 4:
    case 6:
    case 7:
    case 9:
    case 11:
      if (mday >= 1 && mday <= 31)
	return 1;
      break;
    case 3:
    case 5:
    case 8:
    case 10:
      if (mday >= 1 && mday <= 30)
	return 1;
      break;
    case 1:
      if (mday >= 1 && mday <= (__isleap (year) ? 29 : 28))
	return 1;
      break;
    }

  return 0;
}
Exemplo n.º 12
0
Arquivo: grub.c Projeto: tribals/efifs
/* Compute an EFI_TIME representation of a GRUB's mtime_t */
VOID
GrubTimeToEfiTime(const INT32 t, EFI_TIME *tp)
{
	INT32 days, rem, y;
	const unsigned short int *ip;

	days = t / SECS_PER_DAY;
	rem = t % SECS_PER_DAY;
	while (rem < 0) {
		rem += SECS_PER_DAY;
		--days;
	}
	while (rem >= SECS_PER_DAY) {
		rem -= SECS_PER_DAY;
		++days;
	}
	tp->Hour = rem / SECS_PER_HOUR;
	rem %= SECS_PER_HOUR;
	tp->Minute = rem / 60;
	tp->Second = rem % 60;
	y = 1970;

	while (days < 0 || days >= (__isleap (y) ? 366 : 365)) {
		/* Guess a corrected year, assuming 365 days per year. */
		INT32 yg = y + days / 365 - (days % 365 < 0);

		/* Adjust DAYS and Y to match the guessed year. */
		days -= ((yg - y) * 365
			+ LEAPS_THRU_END_OF (yg - 1)
			- LEAPS_THRU_END_OF (y - 1));
		y = yg;
	}
	tp->Year = y;
	ip = __mon_yday[__isleap(y)];
	for (y = 11; days < (long int) ip[y]; --y)
		continue;
	days -= ip[y];
	tp->Month = y + 1;
	tp->Day = days + 1;
}
Exemplo n.º 13
0
struct tm gmtime(unsigned long t)
{
    struct tm tbuf;
    long days, rem;
    int y;
    const unsigned short int *ip;

    days = t / SECS_PER_DAY;
    rem = t % SECS_PER_DAY;

    tbuf.tm_hour = rem / SECS_PER_HOUR;
    rem %= SECS_PER_HOUR;
    tbuf.tm_min = rem / 60;
    tbuf.tm_sec = rem % 60;
    /* January 1, 1970 was a Thursday.  */
    tbuf.tm_wday = (4 + days) % 7;
    if ( tbuf.tm_wday < 0 )
        tbuf.tm_wday += 7;
    y = 1970;
    while ( days >= (rem = __isleap(y) ? 366 : 365) )
    {
        ++y;
        days -= rem;
    }
    while ( days < 0 )
    {
        --y;
        days += __isleap(y) ? 366 : 365;
    }
    tbuf.tm_year = y - 1900;
    tbuf.tm_yday = days;
    ip = (const unsigned short int *)__mon_lengths[__isleap(y)];
    for ( y = 0; days >= ip[y]; ++y )
        days -= ip[y];
    tbuf.tm_mon = y;
    tbuf.tm_mday = days + 1;
    tbuf.tm_isdst = -1;

    return tbuf;
}
Exemplo n.º 14
0
/* week_number computes
*      the ISO 8601  week  number  as  a  decimal  number
*      [01,53].  In the ISO 8601 week-based system, weeks
*      begin on a Monday and week 1 of the  year  is  the
*      week  that includes both January 4th and the first
*      Thursday of the year.   If  the  first  Monday  of
*      January  is  the  2nd,  3rd, or 4th, the preceding
*      days are part of the last week  of  the  preceding
*      year. */
static int week_number(struct tm *tp)
{
    int year = tp->tm_year + TM_YEAR_BASE;
    int days = week_days (tp->tm_yday, tp->tm_wday);

    if (days < 0)
    {
        /* This ISO week belongs to the previous year.  */
        year--;
        days = week_days (tp->tm_yday + (365 + __isleap(year)), tp->tm_wday);
    }
    else
    {
        int d = week_days (tp->tm_yday - (365 + __isleap(year)), tp->tm_wday);
        if (0 <= d)
        {
            /* This ISO week belongs to the next year.  */
            year++;
            days = d;
        }
    }
    return ( (int)days / 7 + 1);
}
Exemplo n.º 15
0
void eTimeCorrectionEditWindow::monthChanged( eListBoxEntryText *e )
{
	if ( e )
	{
		const unsigned char monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int month = (int)e->getKey();
		cday->clear();
		int days = monthdays[month];
		if ( month == 1 && __isleap( (int)cyear->getCurrent()->getKey()) )
			days++;
		for ( int i = 1; i <= days ; i++ )
			new eListBoxEntryText( *cday, eString().sprintf("%02d", i), (void*)i);
		cday->setCurrent( (void*) 1 );
	}
}
Exemplo n.º 16
0
time_t __buildtime(struct tm* tm)
{
    time_t res;
    int leap, daysInMonth;

    // Out-of-range inputs make little sense, fail on them.
    // Note: this introduces incompatibility with the C standard.
    if
    (
        tm->tm_sec  <  0 || tm->tm_sec  > 59 ||
        tm->tm_min  <  0 || tm->tm_min  > 59 ||
        tm->tm_hour <  0 || tm->tm_hour > 23 ||
        tm->tm_mday <  1 || tm->tm_mday > 31 ||
        tm->tm_mon  <  0 || tm->tm_mon  > 11 ||
        tm->tm_year < 70 || tm->tm_year > 70+135
    )
        return (time_t)-1;

    leap = __isleap(1900 + tm->tm_year);

    daysInMonth = (tm->tm_mon == 1) ?
                  28 + leap: // february
                  30 + ((0xAD5 >> tm->tm_mon) & 1); // all other months
    if (tm->tm_mday > daysInMonth) // fail here as well
        return (time_t)-1;

    tm->tm_yday = __DaysSinceJan1st[leap][tm->tm_mon] + tm->tm_mday - 1;

    res = tm->tm_sec +
          tm->tm_min * SECONDS_PER_MINUTE +
          tm->tm_hour * (time_t)SECONDS_PER_HOUR +
          tm->tm_yday * SECONDS_PER_DAY +
          (tm->tm_year - 70) * SECONDS_PER_YEAR;

    // Now account for extra days in the leap years between 1970 and given year:
    //   add a day every 4 years starting in 1973,
    //   subtract a day back out every 100 years starting in 2001, and
    //   add a day back in every 400 years starting in 2001:
    res += ((tm->tm_year-69)>>2) * (time_t)SECONDS_PER_DAY -
           ((tm->tm_year-1)/100) * (time_t)SECONDS_PER_DAY +
           ((tm->tm_year+299)/400) * (time_t)SECONDS_PER_DAY;

    tm->tm_wday = (res / SECONDS_PER_DAY + 4) % 7;

    return res;
}
Exemplo n.º 17
0
s32 dev_rtc_sec_to_date(struct DATE *Dt, struct TIME *Tm, u32 sec)
{
	u32 i,j;
	u32 days;
	const UINT32 *ap;

	days = (sec/SecsPerDay);
	//处理时间
	i = (sec%SecsPerDay);
	Tm->hour = (i/SecsPerHour);
	i = (i%SecsPerHour);
	Tm->min = (i/SecsPerMin);
	Tm->sec = (i%SecsPerMin);
// uart_printf("dev_rtc_sec_to_date:days=%d\r\n", days);	
	//处理周
	Dt->dow = dev_rtc_days_accu_dow(days);
// uart_printf("dows=%d\r\n", Dt->dow); 
	//处理日期
	//处理年
	i = YEAR_STA;
	while(1)
	{	 
		if(__isleap(i))
		{
			//闰年
			j = 366;
		}
		else
		{
			j = 365;
		}
		if(days>=j)
		{
			days -= j;
			i ++;
		}
		else
		{
			break;
		}
	}
	Dt->year = i;
	//处理月
	if(__isleap(i))
	{
		ap = Month_day_Accu_L;
	}
	else
	{
		ap = Month_day_Accu_C;
	}
	for(i=1; i<13; i++)
	{
		if(days < ap[i])
		{
			Dt->mon = i;
			days -= ap[i-1];
			break;
		}
	}
	if(i>=13)return (-1);
	//天
	Dt->day = days+1;
	return 0;
}
Exemplo n.º 18
0
/* Compute the `struct tm' representation of *T,
   offset OFFSET seconds east of UTC,
   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
   Return nonzero if successful.  */
bool timestamp_to_time (uint32_t timestamp, uint16_t offset, struct time_struct *tm)
{
    const unsigned short int __mon_yday[2][13] =
    {
        /* Normal years.  */
        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
        /* Leap years.  */
        { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
    };

    uint32_t days, rem, y;
    const unsigned short int *ip;

    days = timestamp / SECS_PER_DAY;
    rem = timestamp % SECS_PER_DAY;
    rem += offset;

    while (rem < 0)
    {
        rem += SECS_PER_DAY;
        --days;
    }

    while (rem >= SECS_PER_DAY)
    {
        rem -= SECS_PER_DAY;
        ++days;
    }

    tm->tm_hour = rem / SECS_PER_HOUR;

    rem %= SECS_PER_HOUR;
    tm->tm_min = rem / 60;
    tm->tm_sec = rem % 60;
    /* January 1, 1970 was a Thursday.  */
    tm->tm_wday = (4 + days) % 7;

    if (tm->tm_wday < 0)
        tm->tm_wday += 7;

    y = 1970;

#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))

    while (days < 0 || days >= (__isleap (y) ? 366 : 365))
    {
        /* Guess a corrected year, assuming 365 days per year.  */
        long int yg = y + days / 365 - (days % 365 < 0);

        /* Adjust DAYS and Y to match the guessed year.  */
        days -= ( (yg - y) * 365
                  + LEAPS_THRU_END_OF (yg - 1)
                  - LEAPS_THRU_END_OF (y - 1));
        y = yg;
    }

    tm->tm_year = y - 1900;

    if (tm->tm_year != y - 1900)
    {
        /* The year cannot be represented due to overflow.  */
        //__set_errno (EOVERFLOW);
        return false;
    }

    tm->tm_yday = days;

    ip = __mon_yday[__isleap (y) ];

    for (y = 11; days < (long int) ip[y]; --y)
        continue;

    days -= ip[y];

    tm->tm_mon = y;

    tm->tm_mday = days + 1;

    return true;
}
Exemplo n.º 19
0
  char *
strptime_internal (const char *rp, const char *fmt, struct tm *tm,
    enum locale_status *decided)
{
  const char *rp_backup;
  int cnt;
  size_t val;
  int have_I, is_pm;
  int century, want_century;
  int have_wday, want_xday;
  int have_yday;
  int have_mon, have_mday;

  have_I = is_pm = 0;
  century = -1;
  want_century = 0;
  have_wday = want_xday = have_yday = have_mon = have_mday = 0;

  while (*fmt != '\0')
  {
    /* A white space in the format string matches 0 more or white
       space in the input string.  */
    if (isspace (*fmt))
    {
      while (isspace (*rp))
        ++rp;
      ++fmt;
      continue;
    }

    /* Any character but `%' must be matched by the same character
       in the iput string.  */
    if (*fmt != '%')
    {
      match_char (*fmt++, *rp++);
      continue;
    }

    ++fmt;

    /* We need this for handling the `E' modifier.  */
start_over:

    /* Make back up of current processing pointer.  */
    rp_backup = rp;

    switch (*fmt++)
    {
      case '%':
        /* Match the `%' character itself.  */
        match_char ('%', *rp++);
        break;
      case 'a':
      case 'A':
        /* Match day of week.  */
        for (cnt = 0; cnt < 7; ++cnt)
        {
          if (*decided != loc
              && (match_string (weekday_name[cnt], rp)
                || match_string (ab_weekday_name[cnt], rp)))
          {
            *decided = raw;
            break;
          }
        }
        if (cnt == 7)
          /* Does not match a weekday name.  */
          return NULL;
        tm->tm_wday = cnt;
        have_wday = 1;
        break;
      case 'b':
      case 'B':
      case 'h':
        /* Match month name.  */
        for (cnt = 0; cnt < 12; ++cnt)
        {
          if (match_string (month_name[cnt], rp)
              || match_string (ab_month_name[cnt], rp))
          {
            *decided = raw;
            break;
          }
        }
        if (cnt == 12)
          /* Does not match a month name.  */
          return NULL;
        tm->tm_mon = cnt;
        want_xday = 1;
        break;
      case 'c':
        /* Match locale's date and time format.  */
        return strptime_internal (rp, "%x %X", tm, decided);
        break;
      case 'C':
        /* Match century number.  */
        get_number (0, 99, 2);
        century = val;
        want_xday = 1;
        break;
      case 'd':
      case 'e':
        /* Match day of month.  */
        get_number (1, 31, 2);
        tm->tm_mday = val;
        have_mday = 1;
        want_xday = 1;
        break;
      case 'F':
        if (!recursive ("%Y-%m-%d"))
          return NULL;
        want_xday = 1;
        break;
      case 'x':
        {
          char *pic;
          unsigned int loc;
          char winpic[100];
          int ret;

          loc = GetThreadLocale();
          GetLocaleInfo(loc, LOCALE_SSHORTDATE, winpic, 100);

          conv_winpic(winpic, &pic);
          ret = recursive(pic);
          free(pic);
          if (!ret)
            return NULL;
          want_xday = 1;
        }
        break;
      case 'D':
        /* Match standard day format.  */
        if (!recursive ("%m/%d/%y"))
          return NULL;
        want_xday = 1;
        break;
      case 'k':
      case 'H':
        /* Match hour in 24-hour clock.  */
        get_number (0, 23, 2);
        tm->tm_hour = val;
        have_I = 0;
        break;
      case 'I':
        /* Match hour in 12-hour clock.  */
        get_number (1, 12, 2);
        tm->tm_hour = val % 12;
        have_I = 1;
        break;
      case 'j':
        /* Match day number of year.  */
        get_number (1, 366, 3);
        tm->tm_yday = val - 1;
        have_yday = 1;
        break;
      case 'm':
        /* Match number of month.  */
        get_number (1, 12, 2);
        tm->tm_mon = val - 1;
        have_mon = 1;
        want_xday = 1;
        break;
      case 'M':
        /* Match minute.  */
        get_number (0, 59, 2);
        tm->tm_min = val;
        break;
      case 'n':
      case 't':
        /* Match any white space.  */
        while (isspace (*rp))
          ++rp;
        break;
      case 'p':
        /* Match locale's equivalent of AM/PM.  */
        if (!match_string (am_pm[0], rp)) {
          if (match_string (am_pm[1], rp)) {
            is_pm = 1;
          } else {
            return NULL;
          }
        }
        break;
      case 'r':
        return strptime_internal (rp, "%x %X", tm, decided);
        break;
      case 'R':
        if (!recursive ("%H:%M"))
          return NULL;
        break;
      case 's':
        {
          /* The number of seconds may be very high so we cannot use
             the `get_number' macro.  Instead read the number
             character for character and construct the result while
             doing this.  */
          time_t secs = 0;
          if (*rp < '0' || *rp > '9')
            /* We need at least one digit.  */
            return NULL;

          do
          {
            secs *= 10;
            secs += *rp++ - '0';
          }
          while (*rp >= '0' && *rp <= '9');

          if ((tm = localtime (&secs)) == NULL)
            /* Error in function.  */
            return NULL;
        }
        break;
      case 'S':
        get_number (0, 61, 2);
        tm->tm_sec = val;
        break;
      case 'X':
        {
          char *pic;
          unsigned int loc;
          char winpic[100];
          int ret;

          loc = GetThreadLocale();
          GetLocaleInfo(loc, LOCALE_STIMEFORMAT, winpic, 100);

          conv_winpic(winpic, &pic);
          ret = recursive(pic);
          free(pic);
          if (!ret)
            return NULL;
        }
        break;
      case 'T':
        return strptime_internal (rp, "%H:%M:%S", tm, decided);
        break;
      case 'u':
        get_number (1, 7, 1);
        tm->tm_wday = val % 7;
        have_wday = 1;
        break;
      case 'g':
        get_number (0, 99, 2);
        /* XXX This cannot determine any field in TM.  */
        break;
      case 'G':
        if (*rp < '0' || *rp > '9')
          return NULL;
        /* XXX Ignore the number since we would need some more
           information to compute a real date.  */
        do
          ++rp;
        while (*rp >= '0' && *rp <= '9');
        break;
      case 'U':
      case 'V':
      case 'W':
        get_number (0, 53, 2);
        /* XXX This cannot determine any field in TM without some
           information.  */
        break;
      case 'w':
        /* Match number of weekday.  */
        get_number (0, 6, 1);
        tm->tm_wday = val;
        have_wday = 1;
        break;
      case 'y':
        /* Match year within century.  */
        get_number (0, 99, 2);
        /* The "Year 2000: The Millennium Rollover" paper suggests that
           values in the range 69-99 refer to the twentieth century.  */
        tm->tm_year = val >= 69 ? val : val + 100;
        /* Indicate that we want to use the century, if specified.  */
        want_century = 1;
        want_xday = 1;
        break;
      case 'Y':
        /* Match year including century number.  */
        get_number (0, 9999, 4);
        tm->tm_year = val - 1900;
        want_century = 0;
        want_xday = 1;
        break;
      case 'Z':
        /* XXX How to handle this?  */
        break;
      case 'E':
        /* We have no information about the era format.  Just use
           the normal format.  */
        if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
            && *fmt != 'x' && *fmt != 'X')
          /* This is an invalid format.  */
          return NULL;

        goto start_over;
      case 'O':
        switch (*fmt++)
        {
          case 'd':
          case 'e':
            /* Match day of month using alternate numeric symbols.  */
            get_alt_number (1, 31, 2);
            tm->tm_mday = val;
            have_mday = 1;
            want_xday = 1;
            break;
          case 'H':
            /* Match hour in 24-hour clock using alternate numeric
               symbols.  */
            get_alt_number (0, 23, 2);
            tm->tm_hour = val;
            have_I = 0;
            break;
          case 'I':
            /* Match hour in 12-hour clock using alternate numeric
               symbols.  */
            get_alt_number (1, 12, 2);
            tm->tm_hour = val - 1;
            have_I = 1;
            break;
          case 'm':
            /* Match month using alternate numeric symbols.  */
            get_alt_number (1, 12, 2);
            tm->tm_mon = val - 1;
            have_mon = 1;
            want_xday = 1;
            break;
          case 'M':
            /* Match minutes using alternate numeric symbols.  */
            get_alt_number (0, 59, 2);
            tm->tm_min = val;
            break;
          case 'S':
            /* Match seconds using alternate numeric symbols.  */
            get_alt_number (0, 61, 2);
            tm->tm_sec = val;
            break;
          case 'U':
          case 'V':
          case 'W':
            get_alt_number (0, 53, 2);
            /* XXX This cannot determine any field in TM without
               further information.  */
            break;
          case 'w':
            /* Match number of weekday using alternate numeric symbols.  */
            get_alt_number (0, 6, 1);
            tm->tm_wday = val;
            have_wday = 1;
            break;
          case 'y':
            /* Match year within century using alternate numeric symbols.  */
            get_alt_number (0, 99, 2);
            tm->tm_year = val >= 69 ? val : val + 100;
            want_xday = 1;
            break;
          default:
            return NULL;
        }
        break;
      default:
        return NULL;
    }
  }

  if (have_I && is_pm)
    tm->tm_hour += 12;

  if (century != -1)
  {
    if (want_century)
      tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
    else
      /* Only the century, but not the year.  Strange, but so be it.  */
      tm->tm_year = (century - 19) * 100;
  }

  if (want_xday && !have_wday) {
    if ( !(have_mon && have_mday) && have_yday)  {
      /* we don't have tm_mon and/or tm_mday, compute them */
      int t_mon = 0;
      while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
        t_mon++;
      if (!have_mon)
        tm->tm_mon = t_mon - 1;
      if (!have_mday)
        tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1;
    }
    day_of_the_week (tm);
  }
  if (want_xday && !have_yday)
    day_of_the_year (tm);

  return (char *) rp;
}
Exemplo n.º 20
0
static char *
__strptime_internal (const char *rp, const char *fmt, struct tm *tmp, void *statep)
{

  const char *rp_backup;
  const char *rp_longest;
  int cnt;
  int cnt_longest;
  size_t val;
#ifdef _NL_CURRENT
  size_t num_eras;
  struct era_entry *era = NULL;
#endif
  enum ptime_locale_status { nott, loc, raw } decided_longest;
  struct __strptime_state
  {
    unsigned int have_I : 1;
    unsigned int have_wday : 1;
    unsigned int have_yday : 1;
    unsigned int have_mon : 1;
    unsigned int have_mday : 1;
    unsigned int have_uweek : 1;
    unsigned int have_wweek : 1;
    unsigned int is_pm : 1;
    unsigned int want_century : 1;
    unsigned int want_era : 1;
    unsigned int want_xday : 1;
    enum ptime_locale_status decided : 2;
    signed char week_no;
    signed char century;
    int era_cnt;
  } s;
  struct tm tmb;
  struct tm *tm;

  if (statep == NULL)
    {
      memset (&s, 0, sizeof (s));
      s.century = -1;
      s.era_cnt = -1;
#ifdef _NL_CURRENT
      s.decided = nott;
#else
      s.decided = raw;
#endif
      tm = tmp;
    }
  else
    {
      s = *(struct __strptime_state *) statep;
      tmb = *tmp;
      tm = &tmb;
    }

  while (*fmt != '\0')
    {
      /* A white space in the format string matches 0 more or white
     space in the input string.  */
      if (isspace (*fmt))
    {
      while (isspace (*rp))
        ++rp;
      ++fmt;
      continue;
    }

      /* Any character but `%' must be matched by the same character
     in the iput string.  */
      if (*fmt != '%')
    {
      match_char (*fmt++, *rp++);
      continue;
    }

      ++fmt;
      if (statep != NULL)
    {
      /* In recursive calls silently discard strftime modifiers.  */
      while (*fmt == '-' || *fmt == '_' || *fmt == '0'
         || *fmt == '^' || *fmt == '#')
        ++fmt;

      /* And field width.  */
      while (*fmt >= '0' && *fmt <= '9')
        ++fmt;
    }

#ifndef _NL_CURRENT
      /* We need this for handling the `E' modifier.  */
    start_over:
#endif

      /* Make back up of current processing pointer.  */
      rp_backup = rp;

      switch (*fmt++)
    {
    case '%':
      /* Match the `%' character itself.  */
      match_char ('%', *rp++);
      break;
    case 'a':
    case 'A':
      /* Match day of week.  */
      rp_longest = NULL;
      decided_longest = s.decided;
      cnt_longest = -1;
      for (cnt = 0; cnt < 7; ++cnt)
        {
          const char *trp;
#ifdef _NL_CURRENT
          if (s.decided !=raw)
        {
          trp = rp;
          if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), trp)
              && trp > rp_longest)
            {
              rp_longest = trp;
              cnt_longest = cnt;
              if (s.decided == nott
              && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
                     weekday_name[cnt]))
            decided_longest = loc;
            }
          trp = rp;
          if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), trp)
              && trp > rp_longest)
            {
              rp_longest = trp;
              cnt_longest = cnt;
              if (s.decided == nott
              && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
                     ab_weekday_name[cnt]))
            decided_longest = loc;
            }
        }
#endif
          if (s.decided != loc
          && (((trp = rp, match_string (weekday_name[cnt], trp))
               && trp > rp_longest)
              || ((trp = rp, match_string (ab_weekday_name[cnt], rp))
              && trp > rp_longest)))
        {
          rp_longest = trp;
          cnt_longest = cnt;
          decided_longest = raw;
        }
        }
      if (rp_longest == NULL)
        /* Does not match a weekday name.  */
        return NULL;
      rp = rp_longest;
      s.decided = decided_longest;
      tm->tm_wday = cnt_longest;
      s.have_wday = 1;
      break;
    case 'b':
    case 'B':
    case 'h':
      /* Match month name.  */
      rp_longest = NULL;
      decided_longest = s.decided;
      cnt_longest = -1;
      for (cnt = 0; cnt < 12; ++cnt)
        {
          const char *trp;
#ifdef _NL_CURRENT
          if (s.decided !=raw)
        {
          trp = rp;
          if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), trp)
              && trp > rp_longest)
            {
              rp_longest = trp;
              cnt_longest = cnt;
              if (s.decided == nott
              && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
                     month_name[cnt]))
            decided_longest = loc;
            }
          trp = rp;
          if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), trp)
              && trp > rp_longest)
            {
              rp_longest = trp;
              cnt_longest = cnt;
              if (s.decided == nott
              && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
                     ab_month_name[cnt]))
            decided_longest = loc;
            }
        }
#endif
          if (s.decided != loc
          && (((trp = rp, match_string (month_name[cnt], trp))
               && trp > rp_longest)
              || ((trp = rp, match_string (ab_month_name[cnt], trp))
              && trp > rp_longest)))
        {
          rp_longest = trp;
          cnt_longest = cnt;
          decided_longest = raw;
        }
        }
      if (rp_longest == NULL)
        /* Does not match a month name.  */
        return NULL;
      rp = rp_longest;
      s.decided = decided_longest;
      tm->tm_mon = cnt_longest;
      s.have_mon = 1;
      s.want_xday = 1;
      break;
    case 'c':
      /* Match locale's date and time format.  */
#ifdef _NL_CURRENT
      if (s.decided != raw)
        {
          if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
        {
          if (s.decided == loc)
            return NULL;
          else
            rp = rp_backup;
        }
          else
        {
          if (s.decided == nott &&
              strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
            s.decided = loc;
          s.want_xday = 1;
          break;
        }
          s.decided = raw;
        }
#endif
      if (!recursive (HERE_D_T_FMT))
        return NULL;
      s.want_xday = 1;
      break;
    case 'C':
      /* Match century number.  */
#ifdef _NL_CURRENT
    match_century:
#endif
      get_number (0, 99, 2);
      s.century = val;
      s.want_xday = 1;
      break;
    case 'd':
    case 'e':
      /* Match day of month.  */
      get_number (1, 31, 2);
      tm->tm_mday = val;
      s.have_mday = 1;
      s.want_xday = 1;
      break;
    case 'F':
      if (!recursive ("%Y-%m-%d"))
        return NULL;
      s.want_xday = 1;
      break;
    case 'x':
#ifdef _NL_CURRENT
      if (s.decided != raw)
        {
          if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
        {
          if (s.decided == loc)
            return NULL;
          else
            rp = rp_backup;
        }
          else
        {
          if (s.decided == nott
              && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
            s.decided = loc;
          s.want_xday = 1;
          break;
        }
          s.decided = raw;
        }
#endif
      /* Fall through.  */
    case 'D':
      /* Match standard day format.  */
      if (!recursive (HERE_D_FMT))
        return NULL;
      s.want_xday = 1;
      break;
    case 'k':
    case 'H':
      /* Match hour in 24-hour clock.  */
      get_number (0, 23, 2);
      tm->tm_hour = val;
      s.have_I = 0;
      break;
    case 'l':
      /* Match hour in 12-hour clock.  GNU extension.  */
    case 'I':
      /* Match hour in 12-hour clock.  */
      get_number (1, 12, 2);
      tm->tm_hour = val % 12;
      s.have_I = 1;
      break;
    case 'j':
      /* Match day number of year.  */
      get_number (1, 366, 3);
      tm->tm_yday = val - 1;
      s.have_yday = 1;
      break;
    case 'm':
      /* Match number of month.  */
      get_number (1, 12, 2);
      tm->tm_mon = val - 1;
      s.have_mon = 1;
      s.want_xday = 1;
      break;
    case 'M':
      /* Match minute.  */
      get_number (0, 59, 2);
      tm->tm_min = val;
      break;
    case 'n':
    case 't':
      /* Match any white space.  */
      while (isspace (*rp))
        ++rp;
      break;
    case 'p':
      /* Match locale's equivalent of AM/PM.  */
#ifdef _NL_CURRENT
      if (s.decided != raw)
        {
          if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
        {
          if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
            s.decided = loc;
          s.is_pm = 0;
          break;
        }
          if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
        {
          if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
            s.decided = loc;
          s.is_pm = 1;
          break;
        }
          s.decided = raw;
        }
#endif
      if (!match_string (HERE_AM_STR, rp))
        {
          if (match_string (HERE_PM_STR, rp))
        s.is_pm = 1;
          else
        return NULL;
        }
      else
        s.is_pm = 0;
      break;
    case 'r':
#ifdef _NL_CURRENT
      if (s.decided != raw)
        {
          if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
        {
          if (s.decided == loc)
            return NULL;
          else
            rp = rp_backup;
        }
          else
        {
          if (s.decided == nott &&
              strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
                  HERE_T_FMT_AMPM))
            s.decided = loc;
          break;
        }
          s.decided = raw;
        }
#endif
      if (!recursive (HERE_T_FMT_AMPM))
        return NULL;
      break;
    case 'R':
      if (!recursive ("%H:%M"))
        return NULL;
      break;
    case 's':
      {
        /* The number of seconds may be very high so we cannot use
           the `get_number' macro.  Instead read the number
           character for character and construct the result while
           doing this.  */
        time_t secs = 0;
        if (*rp < '0' || *rp > '9')
          /* We need at least one digit.  */
          return NULL;

        do
          {
        secs *= 10;
        secs += *rp++ - '0';
          }
        while (*rp >= '0' && *rp <= '9');

        if (localtime_r (&secs, tm) == NULL)
          /* Error in function.  */
          return NULL;
      }
      break;
    case 'S':
      get_number (0, 61, 2);
      tm->tm_sec = val;
      break;
    case 'X':
#ifdef _NL_CURRENT
      if (s.decided != raw)
        {
          if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
        {
          if (s.decided == loc)
            return NULL;
          else
            rp = rp_backup;
        }
          else
        {
          if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
            s.decided = loc;
          break;
        }
          s.decided = raw;
        }
#endif
      /* Fall through.  */
    case 'T':
      if (!recursive (HERE_T_FMT))
        return NULL;
      break;
    case 'u':
      get_number (1, 7, 1);
      tm->tm_wday = val % 7;
      s.have_wday = 1;
      break;
    case 'g':
      get_number (0, 99, 2);
      /* XXX This cannot determine any field in TM.  */
      break;
    case 'G':
      if (*rp < '0' || *rp > '9')
        return NULL;
      /* XXX Ignore the number since we would need some more
         information to compute a real date.  */
      do
        ++rp;
      while (*rp >= '0' && *rp <= '9');
      break;
    case 'U':
      get_number (0, 53, 2);
      s.week_no = val;
      s.have_uweek = 1;
      break;
    case 'W':
      get_number (0, 53, 2);
      s.week_no = val;
      s.have_wweek = 1;
      break;
    case 'V':
      get_number (0, 53, 2);
      /* XXX This cannot determine any field in TM without some
         information.  */
      break;
    case 'w':
      /* Match number of weekday.  */
      get_number (0, 6, 1);
      tm->tm_wday = val;
      s.have_wday = 1;
      break;
    case 'y':
#ifdef _NL_CURRENT
    match_year_in_century:
#endif
      /* Match year within century.  */
      get_number (0, 99, 2);
      /* The "Year 2000: The Millennium Rollover" paper suggests that
         values in the range 69-99 refer to the twentieth century.  */
      tm->tm_year = val >= 69 ? val : val + 100;
      /* Indicate that we want to use the century, if specified.  */
      s.want_century = 1;
      s.want_xday = 1;
      break;
    case 'Y':
      /* Match year including century number.  */
      get_number (0, 9999, 4);
      tm->tm_year = val - 1900;
      s.want_century = 0;
      s.want_xday = 1;
      break;
    case 'Z':
      /* XXX How to handle this?  */
      break;
    case 'z':
      /* We recognize two formats: if two digits are given, these
         specify hours.  If fours digits are used, minutes are
         also specified.  */
      {
        val = 0;
        while (*rp == ' ')
          ++rp;
        if (*rp != '+' && *rp != '-')
          return NULL;
        rp++;
        int n = 0;
        while (n < 4 && *rp >= '0' && *rp <= '9')
          {
        val = val * 10 + *rp++ - '0';
        ++n;
          }
        if (n == 2)
          val *= 100;
        else if (n != 4)
          /* Only two or four digits recognized.  */
          return NULL;
        else
          {
        /* We have to convert the minutes into decimal.  */
        if (val % 100 >= 60)
          return NULL;
        val = (val / 100) * 100 + ((val % 100) * 50) / 30;
          }
        if (val > 1200)
          return NULL;
      }
      break;
    case 'E':
#ifdef _NL_CURRENT
      switch (*fmt++)
        {
        case 'c':
          /* Match locale's alternate date and time format.  */
          if (s.decided != raw)
        {
          const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);

          if (*fmt == '\0')
            fmt = _NL_CURRENT (LC_TIME, D_T_FMT);

          if (!recursive (fmt))
            {
              if (s.decided == loc)
            return NULL;
              else
            rp = rp_backup;
            }
          else
            {
              if (strcmp (fmt, HERE_D_T_FMT))
            s.decided = loc;
              s.want_xday = 1;
              break;
            }
          s.decided = raw;
        }
          /* The C locale has no era information, so use the
         normal representation.  */
          if (!recursive (HERE_D_T_FMT))
        return NULL;
          s.want_xday = 1;
          break;
        case 'C':
          if (s.decided != raw)
        {
          if (s.era_cnt >= 0)
            {
              era = _nl_select_era_entry (s.era_cnt);
              if (era != NULL && match_string (era->era_name, rp))
            {
              s.decided = loc;
              break;
            }
              else
            return NULL;
            }

          num_eras = _NL_CURRENT_WORD (LC_TIME,
                           _NL_TIME_ERA_NUM_ENTRIES);
          for (s.era_cnt = 0; s.era_cnt < (int) num_eras;
               ++s.era_cnt, rp = rp_backup)
            {
              era = _nl_select_era_entry (s.era_cnt);
              if (era != NULL && match_string (era->era_name, rp))
            {
              s.decided = loc;
              break;
            }
            }
          if (s.era_cnt != (int) num_eras)
            break;

          s.era_cnt = -1;
          if (s.decided == loc)
            return NULL;

          s.decided = raw;
        }
          /* The C locale has no era information, so use the
         normal representation.  */
          goto match_century;
        case 'y':
          if (s.decided != raw)
        {
          get_number(0, 9999, 4);
          tm->tm_year = val;
          s.want_era = 1;
          s.want_xday = 1;
          s.want_century = 1;

          if (s.era_cnt >= 0)
            {
              assert (s.decided == loc);

              era = _nl_select_era_entry (s.era_cnt);
              bool match = false;
              if (era != NULL)
            {
              int delta = ((tm->tm_year - era->offset)
                       * era->absolute_direction);
              match = (delta >= 0
                   && delta < (((int64_t) era->stop_date[0]
                        - (int64_t) era->start_date[0])
                           * era->absolute_direction));
            }
              if (! match)
            return NULL;

              break;
            }

          num_eras = _NL_CURRENT_WORD (LC_TIME,
                           _NL_TIME_ERA_NUM_ENTRIES);
          for (s.era_cnt = 0; s.era_cnt < (int) num_eras; ++s.era_cnt)
            {
              era = _nl_select_era_entry (s.era_cnt);
              if (era != NULL)
            {
              int delta = ((tm->tm_year - era->offset)
                       * era->absolute_direction);
              if (delta >= 0
                  && delta < (((int64_t) era->stop_date[0]
                       - (int64_t) era->start_date[0])
                      * era->absolute_direction))
                {
                  s.decided = loc;
                  break;
                }
            }
            }
          if (s.era_cnt != (int) num_eras)
            break;

          s.era_cnt = -1;
          if (s.decided == loc)
            return NULL;

          s.decided = raw;
        }

          goto match_year_in_century;
        case 'Y':
          if (s.decided != raw)
        {
          num_eras = _NL_CURRENT_WORD (LC_TIME,
                           _NL_TIME_ERA_NUM_ENTRIES);
          for (s.era_cnt = 0; s.era_cnt < (int) num_eras;
               ++s.era_cnt, rp = rp_backup)
            {
              era = _nl_select_era_entry (s.era_cnt);
              if (era != NULL && recursive (era->era_format))
            break;
            }
          if (s.era_cnt == (int) num_eras)
            {
              s.era_cnt = -1;
              if (s.decided == loc)
            return NULL;
              else
            rp = rp_backup;
            }
          else
            {
              s.decided = loc;
              s.era_cnt = -1;
              break;
            }

          s.decided = raw;
        }
          get_number (0, 9999, 4);
          tm->tm_year = val - 1900;
          s.want_century = 0;
          s.want_xday = 1;
          break;
        case 'x':
          if (s.decided != raw)
        {
          const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);

          if (*fmt == '\0')
            fmt = _NL_CURRENT (LC_TIME, D_FMT);

          if (!recursive (fmt))
            {
              if (s.decided == loc)
            return NULL;
              else
            rp = rp_backup;
            }
          else
            {
              if (strcmp (fmt, HERE_D_FMT))
            s.decided = loc;
              break;
            }
          s.decided = raw;
        }
          if (!recursive (HERE_D_FMT))
        return NULL;
          break;
        case 'X':
          if (s.decided != raw)
        {
          const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);

          if (*fmt == '\0')
            fmt = _NL_CURRENT (LC_TIME, T_FMT);

          if (!recursive (fmt))
            {
              if (s.decided == loc)
            return NULL;
              else
            rp = rp_backup;
            }
          else
            {
              if (strcmp (fmt, HERE_T_FMT))
            s.decided = loc;
              break;
            }
          s.decided = raw;
        }
          if (!recursive (HERE_T_FMT))
        return NULL;
          break;
        default:
          return NULL;
        }
      break;
#else
      /* We have no information about the era format.  Just use
         the normal format.  */
      if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
          && *fmt != 'x' && *fmt != 'X')
        /* This is an illegal format.  */
        return NULL;

      goto start_over;
#endif
    case 'O':
      switch (*fmt++)
        {
        case 'd':
        case 'e':
          /* Match day of month using alternate numeric symbols.  */
          get_alt_number (1, 31, 2);
          tm->tm_mday = val;
          s.have_mday = 1;
          s.want_xday = 1;
          break;
        case 'H':
          /* Match hour in 24-hour clock using alternate numeric
         symbols.  */
          get_alt_number (0, 23, 2);
          tm->tm_hour = val;
          s.have_I = 0;
          break;
        case 'I':
          /* Match hour in 12-hour clock using alternate numeric
         symbols.  */
          get_alt_number (1, 12, 2);
          tm->tm_hour = val % 12;
          s.have_I = 1;
          break;
        case 'm':
          /* Match month using alternate numeric symbols.  */
          get_alt_number (1, 12, 2);
          tm->tm_mon = val - 1;
          s.have_mon = 1;
          s.want_xday = 1;
          break;
        case 'M':
          /* Match minutes using alternate numeric symbols.  */
          get_alt_number (0, 59, 2);
          tm->tm_min = val;
          break;
        case 'S':
          /* Match seconds using alternate numeric symbols.  */
          get_alt_number (0, 61, 2);
          tm->tm_sec = val;
          break;
        case 'U':
          get_alt_number (0, 53, 2);
          s.week_no = val;
          s.have_uweek = 1;
          break;
        case 'W':
          get_alt_number (0, 53, 2);
          s.week_no = val;
          s.have_wweek = 1;
          break;
        case 'V':
          get_alt_number (0, 53, 2);
          /* XXX This cannot determine any field in TM without
         further information.  */
          break;
        case 'w':
          /* Match number of weekday using alternate numeric symbols.  */
          get_alt_number (0, 6, 1);
          tm->tm_wday = val;
          s.have_wday = 1;
          break;
        case 'y':
          /* Match year within century using alternate numeric symbols.  */
          get_alt_number (0, 99, 2);
          tm->tm_year = val >= 69 ? val : val + 100;
          s.want_xday = 1;
          break;
        default:
          return NULL;
        }
      break;
    default:
      return NULL;
    }
    }

  if (statep != NULL)
    {
      /* Recursive invocation, returning success, so
     update parent's struct tm and state.  */
      *(struct __strptime_state *) statep = s;
      *tmp = tmb;
      return (char *) rp;
    }

  if (s.have_I && s.is_pm)
    tm->tm_hour += 12;

  if (s.century != -1)
    {
      if (s.want_century)
    tm->tm_year = tm->tm_year % 100 + (s.century - 19) * 100;
      else
    /* Only the century, but not the year.  Strange, but so be it.  */
    tm->tm_year = (s.century - 19) * 100;
    }

  if (s.want_xday && !s.have_wday)
    {
      if ( !(s.have_mon && s.have_mday) && s.have_yday)
    {
      /* We don't have tm_mon and/or tm_mday, compute them.  */
      int t_mon = 0;
      while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
          t_mon++;
      if (!s.have_mon)
          tm->tm_mon = t_mon - 1;
      if (!s.have_mday)
          tm->tm_mday =
        (tm->tm_yday
         - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
      s.have_mon = 1;
      s.have_mday = 1;
    }
      /* Don't crash in day_of_the_week if tm_mon is uninitialized.  */
      if (s.have_mon || (unsigned) tm->tm_mon <= 11)
    day_of_the_week (tm);
    }

  if (s.want_xday && !s.have_yday && (s.have_mon || (unsigned) tm->tm_mon <= 11))
    day_of_the_year (tm);

  if ((s.have_uweek || s.have_wweek) && s.have_wday)
    {
      int save_wday = tm->tm_wday;
      int save_mday = tm->tm_mday;
      int save_mon = tm->tm_mon;
      int w_offset = s.have_uweek ? 0 : 1;

      tm->tm_mday = 1;
      tm->tm_mon = 0;
      day_of_the_week (tm);
      if (s.have_mday)
    tm->tm_mday = save_mday;
      if (s.have_mon)
    tm->tm_mon = save_mon;

      if (!s.have_yday)
    tm->tm_yday = ((7 - (tm->tm_wday - w_offset)) % 7
               + (s.week_no - 1) *7
               + save_wday - w_offset);

      if (!s.have_mday || !s.have_mon)
    {
      int t_mon = 0;
      while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon]
         <= tm->tm_yday)
        t_mon++;
      if (!s.have_mon)
        tm->tm_mon = t_mon - 1;
      if (!s.have_mday)
          tm->tm_mday =
        (tm->tm_yday
         - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
    }

      tm->tm_wday = save_wday;
    }

  return (char *) rp;
}
Exemplo n.º 21
0
/* Compute the day of the year.  */
static void
day_of_the_year (struct tm *tm)
{
  tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
                 + (tm->tm_mday - 1));
}
Exemplo n.º 22
0
  /* Days since 1970 is 365 * number of years + number of leap years since 1970 */
  day  = years * 365 + (years + 1) / 4;

  /* After 2100 we have to substract 3 leap years for every 400 years
     This is not intuitive. Most mktime implementations do not support
     dates after 2059, anyway, so we might leave this out for it's
     bloat. */
  if ((years -= 131) >= 0) {
    years /= 100;
    day -= (years >> 2) * 3 + 1;
    if ((years &= 3) == 3) years--;
    day -= years;
  }

  day += t->tm_yday = __spm [t->tm_mon] + t->tm_mday-1 + ( __isleap (t->tm_year+1900)  &  (t->tm_mon > 1) );

  /* day is now the number of days since 'Jan 1 1970' */
  i = 7;
  t->tm_wday = (day + 4) % i;                        /* Sunday=0, Monday=1, ..., Saturday=6 */

  i = 24;
  day *= i;
  i = 60;
  return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec;
}

time_t mktime(register struct tm* const t) {
  time_t x=timegm(t);
  struct timezone tz;
  gettimeofday(0, &tz);
Exemplo n.º 23
0
int
dysize (int year)
{
  return __isleap (year) ? 366 : 365;
}
Exemplo n.º 24
0
char* strptime(const char* s,const char* format, struct tm* tm) {
  int i,j;
  register time_t  day;
  while (*format) {
    switch (*format) {
    case ' ': case '\t':
      /* match zero or more white space in input string */
      while (isblank(*s)) ++s;
      ++format;
      break;
    case '%':
      ++format;
      switch (*format) {
      case '%': if (*s=='%') ++s; else return 0; break;
      case 'a': case 'A': /* weekday; we just skip */
	for (i=0; i<3; ++i)
	  if (isalpha(*s)) ++s;
	break;
      case 'b': case 'B': case 'h':
	for (i=0; i<12; ++i) {
	  if (strncasecmp(s,months[i],j=strlen(months[i])))
	    if (strncasecmp(s,months[i],j=3))
	      j=0;
	  if (j) break;
	}
	if (!j) return 0;
	s+=j;
	tm->tm_mon=i;
	break;
      case 'c':
	s=strptime(s,"%b %a %d %k:%M:%S %Z %Y",tm);
	break;
      case 'C':
	i=getint(&s,2);
	if (i==-1) return 0;
	tm->tm_year=(tm->tm_year%100)+(i*100);
	break;
      case 'd': case 'e':
	i=getint(&s,2);
	if (i==-1 || i>31) return 0;
	tm->tm_mday=i;
	break;
      case 'D':
	s=strptime(s,"%m/%d/%y",tm);
	break;
      case 'H': case 'k':
	i=getint(&s,2);
	if (i==-1 || i>23) return 0;
	tm->tm_hour=i;
	break;
      case 'I': case 'l':
	i=getint(&s,2);
	if (i==-1 || i>12) return 0;
	tm->tm_hour=(tm->tm_hour/12)*12+i;
	break;
      case 'j':
	getint(&s,3);	/* not used */
	break;
      case 'm':
	i=getint(&s,2);
	if (i<=0 || i>12) return 0;
	tm->tm_mon=i-1;
	break;
      case 'M':
	i=getint(&s,2);
	if (i==-1 || i>59) return 0;
	tm->tm_min=i;
	break;
      case 'n': case 't':
	while (isblank(*s)) ++s;
	break;
      case 'p': case 'P':
	if (*s=='p' || *s=='P') tm->tm_hour=(tm->tm_hour%12)+12;
	s+=2;
	break;
      case 'r':
	s=strptime(s,"%I:%M:%S %p",tm);
	break;
      case 'R':
	s=strptime(s,"%H:%M",tm);
	break;
      case 'S':
	i=getint(&s,2);
	if (i==-1 || i>60) return 0;
	tm->tm_sec=i;
	break;
      case 'T':
	s=strptime(s,"%H:%M:%S",tm);
	break;
      case 'U': case 'W':
	if (getint(&s,2)==-1) return 0;
	break;
      case 'w':
	if (*s<'0' || *s>'6') return 0;
	++s;
	break;
      case 'x':
	s=strptime(s,"%b %a %d",tm);
	break;
      case 'X':
	s=strptime(s,"%k:%M:%S",tm);
	break;
      case 'y':
	i=getint(&s,2);
	if (i<0) return 0;
	tm->tm_year=(i<69)?i+100:i;
	break;
      case 'Y':
	i=getint(&s,4);
	if (i==-1) return 0;
	tm->tm_year=i-1900;
	break;
      case 'Z':
	/* time zone.  Not sure what I'm expected to do here. We'll just
	 * skip to the next whitespace */
	while (*s!=' ' && *s!='\t') ++s;
	break;
      }
      ++format;
      break;
    default:
      if (*s != *format) return 0;
      ++format; ++s;
      break;
    }
  }
 
  day  = (tm->tm_year - 70) * 365 + (tm->tm_year - 69) / 4;
  day += tm->tm_yday = __spm [tm->tm_mon] + tm->tm_mday-1 + (__isleap (tm->tm_year+1900) & (tm->tm_mon > 1));
  tm->tm_wday = (day + 4) % 7;

  return (char*)s;
}
Exemplo n.º 25
0
	/* After 2100 we have to substract 3 leap years for every 400 years
	 This is not intuitive. Most mktime implementations do not support
	 dates after 2059, anyway, so we might leave this out for it's
	 bloat. */
	if (years >= 131)
	{
		years -= 131;
		years /= 100;
		day -= (years >> 2) * 3 + 1;
		if ((years &= 3) == 3)
			years--;
		day -= years;
	}

	day += t->tm_yday = __spm[t->tm_mon] + t->tm_mday - 1 +
			(__isleap(t->tm_year + TM_YEAR_BASE) & (t->tm_mon > 1));

	/* day is now the number of days since 'Jan 1 1970' */
	i = 7;
	t->tm_wday = (day + 4) % i; /* Sunday=0, Monday=1, ..., Saturday=6 */

	i = 24;
	day *= i;
	i = 60;
	return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec;
}

static void num2str(char *c, int i)
{
	c[0] = i / 10 + '0';
	c[1] = i % 10 + '0';