| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /* Copyright (C) 1991, 1993, 1997, 1998, 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
- /******************************************************************************
- 版权所有:
- 文件名称: offtime.c
- 文件版本: 01.01
- 创建作者: sunxi
- 创建日期: 2010-05-06
- 功能说明: 时间格式转化。
- 其它说明: 原始文件来自gcc\glibc-2.6\time\offtime.c
- 修改记录:
- */
- /*------------------------------- 头文件 --------------------------------------
- */
- //#include <linux/time.h>
- #include "head.h"
- /*------------------------------- 宏定义 --------------------------------------
- */
- /* Nonzero if YEAR is a leap year (every 4 years,
- except every 100th isn't, and every 400th is). */
- # define __isleap(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
- #define SECS_PER_HOUR (60 * 60)
- #define SECS_PER_DAY (SECS_PER_HOUR * 24)
- /*------------------------------ 类型结构 -------------------------------------
- */
- /*------------------------------ 全局变量 -------------------------------------
- */
- /* How many days come before each month (0-12). */
- 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
- _mktime(const unsigned int year0, const unsigned int mon0,
- const unsigned int day, const unsigned int hour,
- const unsigned int min, const unsigned int sec);
- /*------------------------------ 外部函数 -------------------------------------
- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
- */
- /******************************************************************************
- 函数名称: rtc_to_timespec
- 函数版本: v1.00
- 创建作者: 杨海涛
- 创建日期: 2011-2-22
- 函数说明: 将rtc_time_t结构的数据转换为timespec格式
- 参数说明:
- p_ts: 输出的timespec结构的时间
- p_rtc: 输入的rtc_time_t结构的时间
- 返回值:
- 0: 成功
- -1: 失败
- 修改记录:
- */
- int rtc_to_timespec(struct rtc_time_t * p_rtc, struct timespec * p_ts)
- {
- #if 1
- if(check_rtc(p_rtc)!= true)
- {
- return -1;
- }
- #else
- if(p_rtc->month > 12 || p_rtc->day > 31 || p_rtc->hour > 24 || p_rtc->min > 60 || p_rtc->ms > 60000)
- {
- return -1;
- }
- #endif
- //将系统时间转换为timespec格式
- p_ts->tv_sec = _mktime(p_rtc->year + 2000, p_rtc->month, p_rtc->day, p_rtc->hour, p_rtc->min, (p_rtc->ms)/1000);
- p_ts->tv_nsec = p_rtc->ms%1000*1000000;
-
- //RTC和GPS中的时间是北京时间(东8区),我们需要将其调整为UTC时间。
- //p_ts->tv_sec -= 8*60*60;
-
- return 0;
- }
- /******************************************************************************
- 函数名称: timespec_to_rtc
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-11-04
- 函数说明: 将timespec结构的数据转换为rtc_time_t格式
- 参数说明:
- ts: 输入的timespec结构的时间
- p_rtc: 输出的rtc_time_t结构的时间
- is_round: 是否需要四舍五入到ms
- 返回值:
- 0: 成功
- 其它: 失败
- 修改记录:
- 2015-5-14: sunxi 增加is_round参数。当只需要ms精度时,应该设置为1,使ms的精度更高;
- 如果需要此函数的结果和ts中ns组成更高精度的时间记录,应设置为0,且使用ns时,
- 也不应该进行四舍五入操作,否则将导致组合出来的时间不正确。(是否难以理解?直接问我好了!)
- */
- int timespec_to_rtc(struct timespec ts, struct rtc_time_t * p_rtc,int is_round)
- {
- long int days, rem, y;
- const unsigned short int *ip;
- if(p_rtc == 0)
- {
- return -1;
- }
- if ((uint32_t)ts.tv_nsec >= NSEC_PER_SEC)
- {
- memset(p_rtc,0,sizeof(*p_rtc));
- return -2;
- }
- // 根据是否需要四舍五入对ms进行处理
- if(is_round)
- {
- ts.tv_nsec += NSEC_PER_MSEC/2;
- if(ts.tv_nsec >= NSEC_PER_SEC)
- {
- ts.tv_nsec -= NSEC_PER_SEC;
- ts.tv_sec++;
- }
- }
- //以日期为界,分开算
- days = ts.tv_sec/ SECS_PER_DAY;
- rem = ts.tv_sec % SECS_PER_DAY;
- //得到时分秒
- p_rtc->hour = rem / SECS_PER_HOUR;
- rem %= SECS_PER_HOUR;
- p_rtc->min= rem / 60;
- // ms,前面已作四舍五入处理
- p_rtc->ms = rem % 60*MSEC_PER_SEC + ts.tv_nsec/NSEC_PER_MSEC;
- #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
- #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
- //算年
- //这个算法有点意思,一下子没有看懂,下次再看
- y = 1970; //UTC
- 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;
- }
- //rtc_time_t中的年从2000年起
- p_rtc->year = y - 2000;
- if (p_rtc->year != y - 2000)
- {
- /* The year cannot be represented due to overflow. */
- memset(p_rtc,0,sizeof(*p_rtc));
- return -3;
- }
- //得到月日
- ip = __mon_yday[__isleap(y)];
- for (y = 11; days < (long int) ip[y]; --y)
- continue;
- days -= ip[y];
-
- //rtc_time_t中month是1~12
- //p_rtc->month = y;
- p_rtc->month = y + 1;
- p_rtc->day = days + 1;
-
- return 0;
- }
- int timespec_to_rtchms(struct timespec ts, struct rtc_time_t * p_rtc,int is_round)
- {
- long int rem;
- if(p_rtc == 0)
- {
- return -1;
- }
- if ((uint32_t)ts.tv_nsec >= NSEC_PER_SEC)
- {
- memset(p_rtc,0,sizeof(*p_rtc));
- return -2;
- }
- // 根据是否需要四舍五入对ms进行处理
- if(is_round)
- {
- ts.tv_nsec += NSEC_PER_MSEC/2;
- if(ts.tv_nsec >= NSEC_PER_SEC)
- {
- ts.tv_nsec -= NSEC_PER_SEC;
- ts.tv_sec++;
- }
- }
- //以日期为界,分开算
- rem = ts.tv_sec % SECS_PER_DAY;
- //得到时分秒
- p_rtc->hour = rem / SECS_PER_HOUR;
- rem %= SECS_PER_HOUR;
- p_rtc->min= rem / 60;
- // ms,前面已作四舍五入处理
- p_rtc->ms = rem % 60*MSEC_PER_SEC + ts.tv_nsec/NSEC_PER_MSEC;
- return 0;
- }
- uint32_t mktimehms(const unsigned int hour,
- const unsigned int min, const unsigned int sec)
- {
- return (uint32_t)((hour*60 + min)*60 + sec); /* finally seconds */
- }
- int check_rtc(struct rtc_time_t *pct)
- {
- //时间有效检查
- if(pct->year>99) return false;
- if(pct->month>12||pct->month<1) return false;
- if(pct->day>31||pct->day<1)return false;
- if(pct->hour>23)return false;
- if(pct->min>59) return false;
- if(pct->ms>=60000) return false;
- if(pct->month==2) // 2月特殊处理
- {
- unsigned short year=pct->year+2000;
- if(year%4==0) //闰年
- {
- if(pct->day>29)return false;
- }
- else
- {
- if(pct->day>28)return false;
- }
- }
- if(pct->month==4||pct->month==6||pct->month==9||pct->month==11)
- {
- if(pct->day>30)
- {
- return false;
- }
- }
- return true;
- }
- /*------------------------------ 内部函数 -------------------------------------
- 内部函数以下划线‘_’开头,不需要检查参数的合法性.
- */
- /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines where long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
- // 本函数来自Linux内核
- uint32_t
- _mktime(const unsigned int year0, const unsigned int mon0,
- const unsigned int day, const unsigned int hour,
- const unsigned int min, const unsigned int sec)
- {
- unsigned int mon = mon0, year = year0;
- /* 1..12 -> 11,12,1..10 */
- if (0 >= (int) (mon -= 2)) {
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return ((((uint32_t)
- (year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
- }
-
- /*------------------------------ 测试函数 -------------------------------------
- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中
- 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数).
- */
- /*------------------------------ 文件结束 -------------------------------------
- */
|