将unix时间戳转换为日期而不使用系统库 [英] Convert unix timestamp to date without system libs

查看:183
本文介绍了将unix时间戳转换为日期而不使用系统库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个嵌入式项目,显示从显示屏上的GPS模块检索的时间,但我也想显示当前日期。我目前有时间作为unix时间戳,并且程序是用C写的。

I am building a embedded project which displays the time retrieved from a GPS module on a display, but I would also like to display the current date. I currently have the time as a unix time stamp and the progject is written in C.

我正在寻找一种从时间戳计算当前UTC日期的方法,闰年考虑?记住,这是一个没有FPU的嵌入式项目,所以浮点数学是模拟的,尽可能避免它的性能。

I am looking for a way to calculate the current UTC date from the timestamp, taking leap years into account? Remember, this is for an embedded project where there is no FPU, so floating point math is emulated, avoiding it as much as possible for performance is required.

编辑

在查看@R ...的代码后,我决定自己写一篇文章,并提出以下内容。 / p>

After looking at @R...'s code, I decided to have a go a writing this myself and came up with the following.

void calcDate(struct tm *tm)
{
  uint32_t seconds, minutes, hours, days, year, month;
  uint32_t dayOfWeek;
  seconds = gpsGetEpoch();

  /* calculate minutes */
  minutes  = seconds / 60;
  seconds -= minutes * 60;
  /* calculate hours */
  hours    = minutes / 60;
  minutes -= hours   * 60;
  /* calculate days */
  days     = hours   / 24;
  hours   -= days    * 24;

  /* Unix time starts in 1970 on a Thursday */
  year      = 1970;
  dayOfWeek = 4;

  while(1)
  {
    bool     leapYear   = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
    uint16_t daysInYear = leapYear ? 366 : 365;
    if (days >= daysInYear)
    {
      dayOfWeek += leapYear ? 2 : 1;
      days      -= daysInYear;
      if (dayOfWeek >= 7)
        dayOfWeek -= 7;
      ++year;
    }
    else
    {
      tm->tm_yday = days;
      dayOfWeek  += days;
      dayOfWeek  %= 7;

      /* calculate the month and day */
      static const uint8_t daysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
      for(month = 0; month < 12; ++month)
      {
        uint8_t dim = daysInMonth[month];

        /* add a day to feburary if this is a leap year */
        if (month == 1 && leapYear)
          ++dim;

        if (days >= dim)
          days -= dim;
        else
          break;
      }
      break;
    }
  }

  tm->tm_sec  = seconds;
  tm->tm_min  = minutes;
  tm->tm_hour = hours;
  tm->tm_mday = days + 1;
  tm->tm_mon  = month;
  tm->tm_year = year;
  tm->tm_wday = dayOfWeek;
}


推荐答案

首先除以86400;其余的可以简单地使用来获得结果的HH:MM:SS部分。现在,自从1970年1月1日以来,你已经有几天了。自2000年3月1日以来,我会将这个数字调整为一个常数,这是天数(可能是负数)这是因为2000年是400年的倍数,闰年周期,使得容易(或至少更容易)计算通过使用部门有多少闰年。

First divide by 86400; the remainder can be used trivially to get the HH:MM:SS part of your result. Now, you're left with a number of days since Jan 1 1970. I would then adjust that by a constant to be the number of days (possibly negative) since Mar 1 2000; this is because 2000 is a multiple of 400, the leap year cycle, making it easy (or at least easier) to count how many leap years have passed using division.

而不是更详细地解释这一点,我会把你引用到我的实现中:

Rather than trying to explain this in more detail, I'll refer you to my implementation:

http://git.musl-libc.org/cgit/musl/tree/src/time/__secs_to_tm .c?h = v0.9.15

这篇关于将unix时间戳转换为日期而不使用系统库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆