Ejemplo n.º 1
0
time_t timegm(struct tm * const t) {
	// time_t is signed on Android.
	static const time_t kTimeMax = ~(1 << (sizeof (time_t) * CHAR_BIT - 1));
	static const time_t kTimeMin = (1 << (sizeof (time_t) * CHAR_BIT - 1));
	time64_t result = timegm64(t);
	if (result < kTimeMin || result > kTimeMax)
		return -1;
	return result;
}
Ejemplo n.º 2
0
static long long millis_from_datetime(PyObject* datetime) {
    struct TM timeinfo;
    long long millis;

    timeinfo.tm_year = PyDateTime_GET_YEAR(datetime) - 1900;
    timeinfo.tm_mon = PyDateTime_GET_MONTH(datetime) - 1;
    timeinfo.tm_mday = PyDateTime_GET_DAY(datetime);
    timeinfo.tm_hour = PyDateTime_DATE_GET_HOUR(datetime);
    timeinfo.tm_min = PyDateTime_DATE_GET_MINUTE(datetime);
    timeinfo.tm_sec = PyDateTime_DATE_GET_SECOND(datetime);

    millis = timegm64(&timeinfo) * 1000;
    millis += PyDateTime_DATE_GET_MICROSECOND(datetime) / 1000;
    return millis;
}
Ejemplo n.º 3
0
BOOL   SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime,  LPFILETIME lpFileTime)
{
  static const int dayoffset[12] = {0, 31, 59, 90, 120, 151, 182, 212, 243, 273, 304, 334};
#if defined(TARGET_DARWIN)
  static long timegm_lock = 0;
#endif

  struct tm sysTime = {};
  sysTime.tm_year = lpSystemTime->wYear - 1900;
  sysTime.tm_mon = lpSystemTime->wMonth - 1;
  sysTime.tm_wday = lpSystemTime->wDayOfWeek;
  sysTime.tm_mday = lpSystemTime->wDay;
  sysTime.tm_hour = lpSystemTime->wHour;
  sysTime.tm_min = lpSystemTime->wMinute;
  sysTime.tm_sec = lpSystemTime->wSecond;
  sysTime.tm_yday = dayoffset[sysTime.tm_mon] + (sysTime.tm_mday - 1);
  sysTime.tm_isdst = g_timezone.m_IsDST;

  // If this is a leap year, and we're past the 28th of Feb, increment tm_yday.
  if (IsLeapYear(lpSystemTime->wYear) && (sysTime.tm_yday > 58))
    sysTime.tm_yday++;

#if defined(TARGET_DARWIN)
  CAtomicSpinLock lock(timegm_lock);
#endif

#if defined(TARGET_ANDROID)
  time64_t t = timegm64(&sysTime);
#else
  time_t t = timegm(&sysTime);
#endif

  LARGE_INTEGER result;
  result.QuadPart = (long long) t * 10000000 + (long long) lpSystemTime->wMilliseconds * 10000;
  result.QuadPart += WIN32_TIME_OFFSET;

  lpFileTime->dwLowDateTime = result.u.LowPart;
  lpFileTime->dwHighDateTime = result.u.HighPart;

  return 1;
}
Ejemplo n.º 4
0
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 + 1, 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 + 1, 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;
}
Ejemplo n.º 5
0
struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm)
{
    time_t safe_time;
    struct tm safe_date;
    struct TM gm_tm;
    Year orig_year;
    int month_diff;

    assert(local_tm != NULL);

    /* Use the system localtime() if time_t is small enough */
    if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) {
        safe_time = *time;

        TRACE1("Using system localtime for %lld\n", *time);

        LOCALTIME_R(&safe_time, &safe_date);

        copy_tm_to_TM(&safe_date, local_tm);
        assert(check_tm(local_tm));

        return local_tm;
    }

    if( gmtime64_r(time, &gm_tm) == NULL ) {
        TRACE1("gmtime64_r returned null for %lld\n", *time);
        return NULL;
    }

    orig_year = gm_tm.tm_year;

    if (gm_tm.tm_year > (2037 - 1900) ||
        gm_tm.tm_year < (1970 - 1900)
       )
    {
        TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year);
        gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900;
    }

    safe_time = timegm64(&gm_tm);
    if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) {
        TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time);
        return NULL;
    }

    copy_tm_to_TM(&safe_date, local_tm);

    local_tm->tm_year = orig_year;
    if( local_tm->tm_year != orig_year ) {
        TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n",
              (Year)local_tm->tm_year, (Year)orig_year);

#ifdef EOVERFLOW
        errno = EOVERFLOW;
#endif
        return NULL;
    }


    month_diff = local_tm->tm_mon - gm_tm.tm_mon;

    /*  When localtime is Dec 31st previous year and
        gmtime is Jan 1st next year.
    */
    if( month_diff == 11 ) {
        local_tm->tm_year--;
    }

    /*  When localtime is Jan 1st, next year and
        gmtime is Dec 31st, previous year.
    */
    if( month_diff == -11 ) {
        local_tm->tm_year++;
    }

    /* GMT is Jan 1st, xx01 year, but localtime is still Dec 31st
       in a non-leap xx00.  There is one point in the cycle
       we can't account for which the safe xx00 year is a leap
       year.  So we need to correct for Dec 31st comming out as
       the 366th day of the year.
    */
    if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 )
        local_tm->tm_yday--;

    assert(check_tm(local_tm));

    return local_tm;
}
Ejemplo n.º 6
0
time_t timegm(struct tm* t)
{
    return (time_t) timegm64(t);
}
Ejemplo n.º 7
0
static bool compose_location(const struct nmea_parser_t *ctx, struct location_t *dst)
{
  const struct nmea_fix_t *fix;
  bool  min_gga, min_rmc, min_gll;
  bool is_valid;
  struct tm time_full;

  fix = &ctx->fix;
  min_gga = fix->gpgga_active && fix->gpgga.has_latitude && fix->gpgga.has_longitude;
  min_rmc = fix->gprmc_active && fix->gprmc.has_latitude && fix->gprmc.has_longitude;
  min_gll = fix->gpgll_active && fix->gpgll.has_latitude && fix->gpgll.has_longitude;

  is_valid = min_gga || min_rmc || min_gll;
  if (fix->gpgga_active)
    is_valid &= fix->gpgga.fix_quality != 0;
  if (fix->gprmc_active)
    is_valid &= fix->gprmc.status_active;

  if (!is_valid) {
    dst->is_valid = false;
    return dst->is_valid;
  }

  dst->is_valid = true;
  time_full = ctx->time_full;
  dst->time = 1000ll * (long long)timegm64(&time_full) + ctx->fix.fix_time.mss;

  // Latitude, longitude
  if (min_gga) {
    dst->latitude = fix->gpgga.latitude;
    dst->longitude = fix->gpgga.longitude;
  }else if(min_rmc) {
    dst->latitude = fix->gprmc.latitude;
    dst->longitude = fix->gprmc.longitude;
  }else {
    assert(min_gll);
    dst->latitude = fix->gpgll.latitude;
    dst->longitude = fix->gpgll.longitude;
  }

  // Altitude
  if (min_gga && fix->gpgga.has_altitude) {
    dst->has_altitude = true;
    dst->altitude = fix->gpgga.altitude;
  }else {
    dst->has_altitude = false;
    dst->altitude = 0;
  }

  // Satellites
  if (min_gga && fix->gpgga.has_sattelites_nb) {
    dst->satellites = fix->gpgga.sattelites_nb;
  }else if (ctx->gpgsa.is_valid) {
    unsigned i;
    dst->satellites = 0;
    for (i=0; i<sizeof(ctx->gpgsa.prn)/sizeof(ctx->gpgsa.prn[0]); ++i) {
      if (ctx->gpgsa.prn[i] > 0)
        dst->satellites += 1;
    }
  }else {
    dst->satellites = -1;
  }

  // Bearing
  if (fix->gprmc_active && fix->gprmc.has_course) {
    dst->has_bearing = true;
    dst->bearing = fix->gprmc.course;
  }else if (ctx->gpvtg.is_valid
      && (ctx->gpvtg.fix_mode != 'N')
      && ctx->gpvtg.has_course_true) {
    dst->has_bearing = true;
    dst->bearing = ctx->gpvtg.course_true;
  }else {
    dst->has_bearing = false;
    dst->bearing = 0;
  }

  // Speed
  if (fix->gprmc_active && fix->gprmc.has_speed) {
    dst->has_speed = true;
    dst->speed = fix->gprmc.speed;
  }else if (ctx->gpvtg.is_valid
      && (ctx->gpvtg.fix_mode != 'N')
      && ctx->gpvtg.has_speed_kmph) {
    dst->has_speed = true;
    dst->speed = ctx->gpvtg.speed_kmph * KMPH_TO_MPS;
  }else {
    dst->has_speed = false;
    dst->speed = 0;
  }

  // Accuracy
  dst->has_accuracy = false;
  dst->accuracy = 0;
  if (fix->gpgst_active) {
    if (fix->gpgst.has_std_lat && fix->gpgst.has_std_lon) {
      dst->has_accuracy = true;
      dst->accuracy = hypotf(fix->gpgst.std_lat, fix->gpgst.std_lon);
    }else if (fix->gpgst.has_range_rms) {
      dst->has_accuracy = true;
      dst->accuracy = fix->gpgst.range_rms;
    }else {
      assert(!dst->has_accuracy);
    }
  }

  return dst->is_valid;
}