Beispiel #1
0
FAR struct tm *gmtime_r(FAR const time_t *timer, FAR struct tm *result)
{
  time_t epoch;
  time_t jdn;
  int    year;
  int    month;
  int    day;
  int    hour;
  int    min;
  int    sec;

  /* Get the seconds since the EPOCH */

  epoch = *timer;
  sdbg("timer=%d\n", (int)epoch);

  /* Convert to days, hours, minutes, and seconds since the EPOCH */

  jdn    = epoch / SEC_PER_DAY;
  epoch -= SEC_PER_DAY * jdn;

  hour   = epoch / SEC_PER_HOUR;
  epoch -= SEC_PER_HOUR * hour;

  min    = epoch / SEC_PER_MIN;
  epoch -= SEC_PER_MIN * min;

  sec    = epoch;

  sdbg("hour=%d min=%d sec=%d\n",
       (int)hour, (int)min, (int)sec);

  /* Convert the days since the EPOCH to calendar day */

  clock_utc2calendar(jdn, &year, &month, &day);

  sdbg("jdn=%d year=%d month=%d day=%d\n",
       (int)jdn, (int)year, (int)month, (int)day);

  /* Then return the struct tm contents */

  result->tm_year  = (int)year - 1900; /* Relative to 1900 */
  result->tm_mon   = (int)month - 1;   /* zero-based */
  result->tm_mday  = (int)day;         /* one-based */
  result->tm_hour  = (int)hour;
  result->tm_min   = (int)min;
  result->tm_sec   = (int)sec;

#if defined(CONFIG_TIME_EXTENDED)
  result->tm_wday  = clock_dayoftheweek(day, month, year);
  result->tm_yday  = day + clock_daysbeforemonth(result->tm_mon, clock_isleapyear(year));
  result->tm_isdst = 0;
#endif

  return result;
}
Beispiel #2
0
time_t mktime(const struct tm *tp)
{
  unsigned int days;

  /* Years since epoch in units of days (ignoring leap years). */

  days = (tp->tm_year - 70) * 365;

  /* Add in the extra days for the leap years prior to the current year. */

  days += (tp->tm_year - 69) >> 2;

  /* Add in the days up to the beginning of this month. */

  days += (time_t)clock_daysbeforemonth(tp->tm_mon, clock_isleapyear(tp->tm_year + 1900));

  /* Add in the days since the beginning of this month (days are 1-based). */

  days += tp->tm_mday - 1;

  /* Then convert the seconds and add in hours, minutes, and seconds */

  return ((days * 24 + tp->tm_hour) * 60 + tp->tm_min) * 60 + tp->tm_sec;
}
Beispiel #3
0
time_t clock_calendar2utc(int year, int month, int day)
{
	time_t days;

	/* Years since epoch in units of days (ignoring leap years). */

	days = (year - EPOCH_YEAR) * 365;

	/* Add in the extra days for the leap years prior to the current year. */

	days += (year - EPOCH_YEAR - 1) >> 2;

	/* Add in the days up to the beginning of this month. */

	days += (time_t)clock_daysbeforemonth(month, clock_isleapyear(year));

	/* Add in the days since the beginning of this month (days are 1-based). */

	days += day - 1;

	/* Then convert the seconds and add in hours, minutes, and seconds */

	return days;
}
Beispiel #4
0
static void clock_utc2calendar(time_t days, int *year, int *month, int *day)
{
  int  value;
  int  min;
  int  max;
  int  tmp;
  bool leapyear;

  /* There is one leap year every four years, so we can get close with the
   * following:
   */

  value   = days  / (4*365 + 1);  /* Number of 4-years periods since the epoch*/
  days   -= value * (4*365 + 1);  /* Remaining days */
  value <<= 2;                    /* Years since the epoch */

  /* Then we will brute force the next 0-3 years */

  for (;;)
    {
      /* Is this year a leap year (we'll need this later too) */

      leapyear = clock_isleapyear(value + 1970);

      /* Get the number of days in the year */

      tmp = (leapyear ? 366 : 365);

      /* Do we have that many days? */

      if (days >= tmp)
        {
           /* Yes.. bump up the year */

           value++;
           days -= tmp;
        }
      else
        {
           /* Nope... then go handle months */

           break;
        }
    }

  /* At this point, value has the year and days has number days into this year */

  *year = 1970 + value;

  /* Handle the month (zero based) */

  min = 0;
  max = 11;

  do
    {
      /* Get the midpoint */

      value = (min + max) >> 1;

      /* Get the number of days that occurred before the beginning of the month
       * following the midpoint.
      */

      tmp = clock_daysbeforemonth(value + 1, leapyear);

      /* Does the number of days before this month that equal or exceed the
       * number of days we have remaining?
       */

      if (tmp > days)
        {
          /* Yes.. then the month we want is somewhere from 'min' and to the
           * midpoint, 'value'.  Could it be the midpoint?
           */

          tmp = clock_daysbeforemonth(value, leapyear);
          if (tmp > days)
            {
              /* No... The one we want is somewhere between min and value-1 */

              max = value - 1;
            }
          else
            {
              /* Yes.. 'value' contains the month that we want */

              break;
            }
        }
      else
        {
           /* No... The one we want is somwhere between value+1 and max */

           min = value + 1;
        }

      /* If we break out of the loop because min == max, then we want value
       * to be equal to min == max.
       */

      value = min;
    }
  while (min < max);

  /* The selected month number is in value. Subtract the number of days in the
   * selected month
   */

  days -= clock_daysbeforemonth(value, leapyear);

  /* At this point, value has the month into this year (zero based) and days has
   * number of days into this month (zero based)
   */

  *month = value + 1; /* 1-based */
  *day   = days + 1;  /* 1-based */
}
Beispiel #5
0
size_t strftime(FAR char *s, size_t max, FAR const char *format,
                FAR const struct tm *tm)
{
  FAR const char *str;
  FAR char       *dest   = s;
  int             chleft = max;
  int             value;
  int             len;

  while (*format && chleft > 0)
    {
      /* Just copy regular characters */

      if (*format != '%')
        {
           *dest++ = *format++;
           chleft--;
           continue;
        }

      /* Handle the format character */

       format++;
       len   = 0;

       switch (*format++)
         {
           /* %a: A three-letter abbreviation for the day of the week. */
           /* %A: The full name for the day of the week. */

           case 'a':
           case 'A':
             {
               len = snprintf(dest, chleft, "Day"); /* Not supported */
             }
             break;

           /* %h: Equivalent to %b */

           case 'h':

           /* %b: The abbreviated month name according to the current locale. */

           case 'b':
             {
               if (tm->tm_mon < 12)
                 {
                   str = g_abbrevmonthname[tm->tm_mon];
                   len = snprintf(dest, chleft, "%s", str);
                 }
             }
             break;

           /* %B: The full month name according to the current locale. */

           case 'B':
             {
               if (tm->tm_mon < 12)
                 {
                   str = g_monthname[tm->tm_mon];
                   len = snprintf(dest, chleft, "%s", str);
                 }
             }
             break;

           /* %y: The year as a decimal number without a century (range 00 to 99). */

           case 'y':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_year % 100);
             }
             break;

           /* %C: The century number (year/100) as a 2-digit integer. */

           case 'C':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_year / 100);
             }
             break;

           /* %d: The day of the month as a decimal number (range 01 to 31). */

           case 'd':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_mday);
             }
             break;

           /* %e: Like %d, the day of the month as a decimal number, but a leading
            * zero is replaced by a space.
            */

           case 'e':
             {
               len = snprintf(dest, chleft, "%2d", tm->tm_mday);
             }
             break;

           /* %H: The hour as a decimal number using a 24-hour clock (range 00  to 23). */

           case 'H':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_hour);
             }
             break;

           /* %I: The  hour as a decimal number using a 12-hour clock (range 01 to 12). */

           case 'I':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_hour % 12);
             }
             break;

           /* %j: The day of the year as a decimal number (range 001 to 366). */

           case 'j':
             {
               if (tm->tm_mon < 12)
                 {
                   value = clock_daysbeforemonth(tm->tm_mon, clock_isleapyear(tm->tm_year)) + tm->tm_mday;
                   len   = snprintf(dest, chleft, "%03d", value);
                 }
             }
             break;

           /* %k: The hour (24-hour clock) as a decimal number (range  0  to  23);
            * single digits are preceded by a blank.
            */

           case 'k':
             {
               len = snprintf(dest, chleft, "%2d", tm->tm_hour);
             }
             break;

           /* %l: The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
            * single digits are preceded by a blank.
            */

           case 'l':
             {
               len = snprintf(dest, chleft, "%2d", tm->tm_hour % 12);
             }
             break;

           /* %m: The month as a decimal number (range 01 to 12). */

           case 'm':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_mon + 1);
             }
             break;

           /* %M: The minute as a decimal number (range 00 to 59). */

           case 'M':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_min);
             }
             break;

           /* %n: A newline character. */

           case 'n':
             {
               *dest = '\n';
               len   = 1;
             }
             break;

           /* %p: Either "AM" or "PM" according to the given time  value. */

           case 'p':
             {
               if (tm->tm_hour >= 12)
                 {
                   str = "PM";
                 }
               else
                 {
                   str = "AM";
                 }
               len = snprintf(dest, chleft, "%s", str);
             }
             break;

           /* %P: Like %p but in lowercase: "am" or "pm" */

           case 'P':
             {
               if (tm->tm_hour >= 12)
                 {
                   str = "pm";
                 }
               else
                 {
                   str = "am";
                 }
               len = snprintf(dest, chleft, "%s", str);
             }
             break;

           /* %s: The number of seconds since the Epoch, that is, since 1970-01-01
            * 00:00:00 UTC.  Hmmm... mktime argume is not 'const'.
            */

           case 's':
             {
               len = snprintf(dest, chleft, "%d", mktime((FAR struct tm *)tm));
             }
             break;

           /* %S: The second as a decimal number (range 00 to 60).  (The range  is
            * up to 60 to allow for occasional leap seconds.)
            */

           case 'S':
             {
               len = snprintf(dest, chleft, "%02d", tm->tm_sec);
             }
             break;

           /* %t: A tab character. */

           case 't':
             {
               *dest = '\t';
               len   = 1;
             }
             break;

           /* %Y: The year as a decimal number including the century. */

           case 'Y':
             {
               len = snprintf(dest, chleft, "%04d", tm->tm_year + 1900);
             }
             break;

           /* %%:  A literal '%' character. */

           case '%':
             {
               *dest = '%';
               len   = 1;
             }
             break;
        }

      /* Update counts and pointers */

      dest   += len;
      chleft -= len;
    }

  /* We get here because either we have reached the end of the format string
   * or because there is no more space in the user-provided buffer and the
   * resulting string has been truncated.
   *
   * Is there space remaining in the user-provided buffer for the NUL
   * terminator?
   */

  if (chleft > 0)
    {
      /* Yes, append terminating NUL byte */

      *dest = '\0';

      /* And return the number of bytes in the resulting string (excluding
       * the NUL terminator).
       */

      return max - chleft;
    }

  /* The string was truncated and/or not properly terminated.  Return
   * zero.
   */

  return 0;
}