[嵌入式开发模块]C语言ANSI标准库time.h实现 CodeWarrior必备!

前言

想当年初学C/C++程序设计(吐槽一下,大学里用都的啥乐色教材,推荐还是直接买外国经典教材自学)的时候,一遇到需要时间的时候,就会引入时间标准库time.h。用的甚是愉快。

如今用CodeWarrior做项目也想用到它,结果发现

什么鬼!CodeWarrior居然根本没有这个ANSI标准库的实现。至于time函数能够编译通过,我去看了下源码。CodwWarrior提供了仿真器上获取时间的实现,没甚意义。

但是实际项目中一般都会用到时间的呀!于是自己折腾了半天,找到VS的源码,各种移植。总算搞出了这个实现。

本来是准备用宏替换技术使得新的实现和原来的标准库声明完全一致的,但是写着写着发现比如asctime这种返回一个指向字符串的指针的接口很不靠谱,还得内部管理内存。于是就稍微改了一改接口声明。但这样就不好直接替换了。

再想一想,一般通用的模块中是不会直接使用time.h的,用的都是在业务代码中。于是就干脆直接不完全按照标准库的接口了,加了个前缀。

用法反正和标准库一模一样,直接查time标准库的接口怎么用就会了。

另外,默认是用在中国的,所以不支持夏令时等功能。而且要注意的是,由于time_t是32位的,由于时间格式限制,这个模块只支持1970年到大约2100年, 在windows上由于time_t是32位有符号的,所以只到2038年那样,而CodeWarrior上是无符号的,所以能到2100多十几年那样,但是由于代码中没有考虑2100年的闰年处理,所以其实到2100年3月那样就会出问题。不过。。管他的呢。那时候我们在不在都还是个问题。。

源代码中由于很多地方是复制后进行修改的,还比较凌乱,大家就不要看源码,直接调接口就好了 0.0

源码中依赖了一个MyOS.h模块,出现了几次:

  MyOS_SR sr;
  sr = MyOS_disableInterrupts();
  //......
  MyOS_enableInterrupts(sr);

这是自己做的操作系统抽象层,用来开关中断的。不用太在意,照着实现一下就好。或者直接替换成平台上开关中断的函数就行。

源码

TimeExt.h

/*
*******************************************************************************************
*
*                                 TIME MODULE FOR CODEWARRIOR
*
* File : TimeExt.h
* By   : Lin Shijun(https://blog.csdn.net/lin_strong)
* Date:  2019/09/26
* version: V1.0
* NOTE(s):a. This module implements the time.h, which is not provided by codewarrior IDE.
*         b. It's adapted from the library of VS2012, but modified a lot.
*         c. the time_t in VS2012 is int32_t, but in CW, is uint32_t, so we can provide
*            support for a longer time till about 2100, which in VS2012 is about 2038.
*         d. Though, uint32_t can support serveral years after 2100, but the implementation
*            here treat 2100 as leap year, so, don't use this library after 2100.02.28, 
*            or you can fix this yourself.
*         e. Now, we assume you will call TimeExt_clocktick() in interrupt per millisecond.
*         f. Now, we don't supoprt DST(Daylight saving time) for this module is implemented
*            for China.
*********************************************************************************************
*/
#ifndef _TIME_EXT_H
#define _TIME_EXT_H

#ifdef __cplusplus
extern "C" {
#endif

/*
******************************************************************************************
*                                     INCLUDES
******************************************************************************************
*/

#include <time.h>
#include <stdint.h>

/*
******************************************************************************************
*                                     CONSTANT
******************************************************************************************
*/

#undef CLOCKS_PER_SEC
#define CLOCKS_PER_SEC 1000

/*
******************************************************************************************
*                                 PUBLIC INTERFACES
******************************************************************************************
*/

//if a given year is a leap year.
#define IS_LEAP_YEAR(y)  ((((y) % 4 == 0) && ((y) % 100 != 0)) || ((y) % 400 == 0))

int TimeExt_asctime(char * buf, const struct tm *time_rec);
int TimeExt_ctime(char * buf, const time_t *time_val);
clock_t TimeExt_clock(void);
time_t TimeExt_difftime(time_t t1, time_t t2);
void TimeExt_gmtime(struct tm * ret, const time_t *time_val);
void TimeExt_localtime(struct tm * ret,const time_t *time_val);
time_t TimeExt_mktime(struct tm *time_rec);
time_t TimeExt_mkgmtime(struct tm *time_rec);
//size_t TimeExt_strftime(char *s, size_t n, const char *format, const struct tm *time_rec);
time_t TimeExt_time (time_t *time_val);

/*
******************************************************************************************
*                                INTERNAL INTERFACES
******************************************************************************************
*/

void TimeExt_setgmtime(const time_t *time_val, uint32_t us);
// internal call by system in interrupt to notify a clock tick
void TimeExt_clocktick(void);
// gmttime + getTimezoneOffset() = localtime
int32_t getTimezoneOffset(void);

extern const int16_t TimeExt_lpdays[];
extern const int16_t TimeExt_days[];
#ifdef __cplusplus
 }
#endif

#endif

TimeExt.c

/*
*******************************************************************************************
*
*                                 TIME MODULE FOR CODEWARRIOR
*
* File : TimeExt.c
* By   : Lin Shijun(https://blog.csdn.net/lin_strong)
* Date:  2019/09/26
* version: V1.0
* NOTE(s):
*********************************************************************************************
*/

/*
******************************************************************************************
*                                     INCLUDES
******************************************************************************************
*/
#include "timeExt.h"
#include "MyOS.h"
#include <string.h>
#include <stdio.h>

#if(CLOCKS_PER_SEC != 1000)
#error "this implementation assume the clock tick per ms"
#endif

/*
******************************************************************************************
*                                     CONSTANTS
******************************************************************************************
*/

#define _MIN_SEC           60L
#define _HOUR_SEC          (60  * _MIN_SEC)
#define _DAY_SEC           (24  * _HOUR_SEC)    /* secs in a day */
#define _YEAR_SEC          (365 * _DAY_SEC)     /* secs in a year */
#define _FOUR_YEAR_SEC     (1461 * _DAY_SEC)    /* secs in a 4 year interval */
#define _BASE_YEAR         70                   /* 1970 is the base year */
#define _BASE_DOW          4                    /* 01-01-70 was a Thursday */
#define _LEAP_YEAR_ADJUST  17                   /* Leap years 1900 - 1970 */

const int16_t TimeExt_lpdays[] = {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
const int16_t TimeExt_days[] = {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364};
static const char _dnames[] = {"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat"};
static const char _mnames[] = {"Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"};

/*
******************************************************************************************
*                              LOCAL FUNCTIONS DECLARATION
******************************************************************************************
*/


/*
 * ChkAdd evaluates to TRUE if dest = src1 + src2 has overflowed
 */
//#define ChkAdd(dest, src1, src2)   ( ((src1 >= 0L) && (src2 >= 0L) \
//    && (dest < 0L)) || ((src1 < 0L) && (src2 < 0L) && (dest >= 0L)) )

// return TRUE if dest = src1 + src2 has overflowed. dest, src1 & src2 are all unsigned type
#define ChkAdd(dest, src1, src2)   ((dest) < (src1) && (dest) < (src2))

// return TRUE if if dest = src1 * src2 has overflowed
#define ChkMul(dest, src1, src2)   ((src1)? ((dest)/(src1) != (src2)) : 0 )

static time_t _make_time(struct tm *time_rec, int ultflag);

/*
******************************************************************************************
*                                   CONFIGURATION
******************************************************************************************
*/
 /*
00)UTC-12:00 Baker Island, Howland Island (both uninhabited)
01) UTC-11:00 American Samoa, Samoa
02) UTC-10:00 (Summer)French Polynesia (most), United States (Aleutian Islands, Hawaii)
03) UTC-09:30 Marquesas Islands
04) UTC-09:00 Gambier Islands;(Summer)United States (most of Alaska)
05) UTC-08:00 (Summer)Canada (most of British Columbia), Mexico (Baja California)
06) UTC-08:00 United States (California, most of Nevada, most of Oregon, Washington (state))
07) UTC-07:00 Mexico (Sonora), United States (Arizona); (Summer)Canada (Alberta)
08) UTC-07:00 Mexico (Chihuahua), United States (Colorado)
09) UTC-06:00 Costa Rica, El Salvador, Ecuador (Galapagos Islands), Guatemala, Honduras
10) UTC-06:00 Mexico (most), Nicaragua;(Summer)Canada (Manitoba, Saskatchewan), United States (Illinois, most of Texas)
11) UTC-05:00 Colombia, Cuba, Ecuador (continental), Haiti, Jamaica, Panama, Peru
12) UTC-05:00 (Summer)Canada (most of Ontario, most of Quebec)
13) UTC-05:00 United States (most of Florida, Georgia, Massachusetts, most of Michigan, New York, North Carolina, Ohio, Washington D.C.)
14) UTC-04:30 Venezuela
15) UTC-04:00 Bolivia, Brazil (Amazonas), Chile (continental), Dominican Republic, Canada (Nova Scotia), Paraguay,
16) UTC-04:00 Puerto Rico, Trinidad and Tobago
17) UTC-03:30 Canada (Newfoundland)
18) UTC-03:00 Argentina; (Summer) Brazil (Brasilia, Rio de Janeiro, Sao Paulo), most of Greenland, Uruguay
19) UTC-02:00 Brazil (Fernando de Noronha), South Georgia and the South Sandwich Islands
20) UTC-01:00 Portugal (Azores), Cape Verde
21) UTC&#177;00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira)
22) UTC&#177;00:00 Spain (Canary Islands), Morocco, United Kingdom
23) UTC+01:00 Angola, Cameroon, Nigeria, Tunisia; (Summer)Albania, Algeria, Austria, Belgium, Bosnia and Herzegovina,
24) UTC+01:00 Spain (continental), Croatia, Czech Republic, Denmark, Germany, Hungary, Italy, Kinshasa, Kosovo,
25) UTC+01:00 Macedonia, France (metropolitan), the Netherlands, Norway, Poland, Serbia, Slovakia, Slovenia, Sweden, Switzerland
26) UTC+02:00 Libya, Egypt, Malawi, Mozambique, South Africa, Zambia, Zimbabwe, (Summer)Bulgaria, Cyprus, Estonia,
27) UTC+02:00 Finland, Greece, Israel, Jordan, Latvia, Lebanon, Lithuania, Moldova, Palestine, Romania, Syria, Turkey, Ukraine
28) UTC+03:00 Belarus, Djibouti, Eritrea, Ethiopia, Iraq, Kenya, Madagascar, Russia (Kaliningrad Oblast), Saudi Arabia,
29) UTC+03:00 South Sudan, Sudan, Somalia, South Sudan, Tanzania, Uganda, Yemen
30) UTC+03:30 (Summer)Iran
31) UTC+04:00 Armenia, Azerbaijan, Georgia, Mauritius, Oman, Russia (European), Seychelles, United Arab Emirates
32) UTC+04:30 Afghanistan
33) UTC+05:00 Kazakhstan (West), Maldives, Pakistan, Uzbekistan
34) UTC+05:30 India, Sri Lanka
35) UTC+05:45 Nepal
36) UTC+06:00 Kazakhstan (most), Bangladesh, Russia (Ural: Sverdlovsk Oblast, Chelyabinsk Oblast)
37) UTC+06:30 Cocos Islands, Myanmar
38) UTC+07:00 Jakarta, Russia (Novosibirsk Oblast), Thailand, Vietnam
39) UTC+08:00 China, Hong Kong, Russia (Krasnoyarsk Krai), Malaysia, Philippines, Singapore, Taiwan, most of Mongolia, Western Australia
40) UTC+09:00 Korea, East Timor, Russia (Irkutsk Oblast), Japan
41) UTC+09:30 Australia (Northern Territory);(Summer)Australia (South Australia))
42) UTC+10:00 Russia (Zabaykalsky Krai); (Summer)Australia (New South Wales, Queensland, Tasmania, Victoria)
43) UTC+10:30 Lord Howe Island
44) UTC+11:00 New Caledonia, Russia (Primorsky Krai), Solomon Islands
45) UTC+11:30 Norfolk Island
46) UTC+12:00 Fiji, Russia (Kamchatka Krai);(Summer)New Zealand
47) UTC+12:45 (Summer)New Zealand
48) UTC+13:00 Tonga
49) UTC+14:00 Kiribati (Line Islands)
*/

// timezone china
static const uint8_t time_zone = 39;

/*
******************************************************************************************
*                                     LOCAL VARIABLES
******************************************************************************************
*/
static clock_t _ticks;
static time_t _seconds;
static uint32_t _useconds = 0;

/*
******************************************************************************************
*                              PUBLIC INTERFACES IMPLEMENTATION
******************************************************************************************
*/
int TimeExt_asctime(char * buf, const struct tm *time_rec){
  if(buf == NULL || time_rec == NULL )
    return -1;
  if(time_rec->tm_year < 0 ||
     time_rec->tm_mon  < 0 || time_rec->tm_mon  > 11 ||
     time_rec->tm_hour < 0 || time_rec->tm_hour > 23 ||
     time_rec->tm_min  < 0 || time_rec->tm_min  > 59 ||
     time_rec->tm_sec  < 0 || time_rec->tm_sec  > 59 ||
     time_rec->tm_wday < 0 || time_rec->tm_wday > 6)
    return -1;
  if(time_rec->tm_mday < 1 || 
    // Day is not in valid range for the month
    ( ( TimeExt_days[ time_rec->tm_mon + 1 ] - TimeExt_days[ time_rec->tm_mon ] ) < time_rec->tm_mday ) ||
    
    // Special case for Feb in a leap year
    (  IS_LEAP_YEAR( time_rec->tm_year + 1900) 
    
    && ( time_rec->tm_mon == 1 ) 
    
    && ( time_rec->tm_mday > 29 )))
    return -1;
  
  return snprintf(buf, 26, "%s %s %02d %02d:%02d:%02d %04d\n",_dnames + time_rec->tm_wday * 4,
     _mnames + time_rec->tm_mon * 4, time_rec->tm_mday, time_rec->tm_hour, time_rec->tm_min, time_rec->tm_sec,
     time_rec->tm_year + 1900);
}

int TimeExt_ctime(char * buf, const time_t *time_val){
  struct tm tmp;
  TimeExt_localtime(&tmp, time_val);
  return TimeExt_asctime(buf, &tmp);
}

clock_t TimeExt_clock(void){
  clock_t ret;
  MyOS_SR sr;
  sr = MyOS_disableInterrupts();
  ret = _ticks;
  MyOS_enableInterrupts(sr);
  return ret;
}

time_t TimeExt_difftime(time_t t1, time_t t2){
  return t1 - t2;
}

void TimeExt_gmtime(struct tm * ret, const time_t *time_val){
  time_t caltim;/* = *time_val; */  /* calendar time to convert */
  int islpyr = 0;                   /* is-current-year-a-leap-year flag */
  int tmptim;
  const int16_t *mdays;                       /* pointer to days or lpdays */
  
  if(ret == NULL || time_val == NULL)
    return;
  
  (void)memset(ret, 0xff, sizeof( struct tm ) );

  caltim = *time_val;
  
  // Determine years since 1970. note that 2000 IS a leap year but 2100 is not 
  // so ,this function has bug after 2100
  // TODO: fix this
  tmptim = (int)(caltim / _FOUR_YEAR_SEC);
  caltim -= ((time_t)tmptim * _FOUR_YEAR_SEC);

  /*
   * Determine which year of the interval
   */
  tmptim = (tmptim * 4) + 70;         /* 1970, 1974, 1978,...,etc. */

  if ( caltim >= _YEAR_SEC ) {

      tmptim++;                       /* 1971, 1975, 1979,...,etc. */
      caltim -= _YEAR_SEC;

      if ( caltim >= _YEAR_SEC ) {

          tmptim++;                   /* 1972, 1976, 1980,...,etc. */
          caltim -= _YEAR_SEC;

          /*
           * Note, it takes 366 days-worth of seconds to get past a leap
           * year.
           */
          if ( caltim >= (_YEAR_SEC + _DAY_SEC) ) {

                  tmptim++;           /* 1973, 1977, 1981,...,etc. */
                  caltim -= (_YEAR_SEC + _DAY_SEC);
          }
          else {
                  /*
                   * In a leap year after all, set the flag.
                   */
                  islpyr++;
          }
      }
  }
 
  /*
   * tmptim now holds the value for tm_year. caltim now holds the
   * number of elapsed seconds since the beginning of that year.
   */
  ret->tm_year = tmptim;

  /*
   * Determine days since January 1 (0 - 365). This is the tm_yday value.
   * Leave caltim with number of elapsed seconds in that day.
   */
  ret->tm_yday = (int)(caltim / _DAY_SEC);
  caltim -= (time_t)(ret->tm_yday) * _DAY_SEC;

  /*
   * Determine months since January (0 - 11) and day of month (1 - 31)
   */
  if ( islpyr )
      mdays = TimeExt_lpdays;
  else
      mdays = TimeExt_days;


  for ( tmptim = 1 ; mdays[tmptim] < ret->tm_yday ; tmptim++ ) ;

  ret->tm_mon = --tmptim;

  ret->tm_mday = ret->tm_yday - mdays[tmptim];
 
  /*
   * Determine days since Sunday (0 - 6)
   */
  ret->tm_wday = ((*time_val / _DAY_SEC) + _BASE_DOW) % 7;

  /*
   *  Determine hours since midnight (0 - 23), minutes after the hour
   *  (0 - 59), and seconds after the minute (0 - 59).
   */
  ret->tm_hour = (int)(caltim / 3600);
  caltim -= (time_t)ret->tm_hour * 3600L;

  ret->tm_min = (int)(caltim / 60);
  ret->tm_sec = (int)(caltim - (ret->tm_min) * 60);

  ret->tm_isdst = 0;
}

void TimeExt_localtime(struct tm * ret,const time_t *time_val){
  time_t ltime = *time_val + getTimezoneOffset();
  TimeExt_gmtime(ret, &ltime);
}

time_t TimeExt_mktime(struct tm *time_rec){
  return(_make_time(time_rec, 1));
}

time_t TimeExt_mkgmtime(struct tm *time_rec){
  return(_make_time(time_rec, 0));
}

// 暂时不实现它
//size_t strftime(char *s, size_t n, const char *format, const struct tm *time_rec);

time_t TimeExt_time (time_t *time_val){
  time_t ret;
  MyOS_SR sr;
  sr = MyOS_disableInterrupts();
  ret = _seconds;
  MyOS_enableInterrupts(sr);
  if(time_val)
    *time_val = ret;
  return ret;
}

void TimeExt_clocktick(void){
// 预计会在中断中执行,所以不需要调用系统的禁止中断
  ++_ticks;
  _useconds += 1000;        // 因为现在默认1毫秒(1000微秒)tick一下
  if(_useconds >= 1000000){
    _useconds %= 1000;
    ++_seconds;
  }
}

void TimeExt_setgmtime(const time_t *time_val, uint32_t us){
  MyOS_SR sr;
  sr = MyOS_disableInterrupts();
  _seconds = *time_val;
  _useconds = us;
  MyOS_enableInterrupts(sr);
}


#pragma MESSAGE DISABLE C4001
#pragma MESSAGE DISABLE C5908
#pragma MESSAGE DISABLE C5660


int32_t getTimezoneOffset(void){
  switch (time_zone){
  case 0:
    return -12 * _HOUR_SEC;
  case 1:
    return -11 * _HOUR_SEC;
  case 2:
    return -10 * _HOUR_SEC;
  case 3:
    return -(9 * _HOUR_SEC + 30 * _MIN_SEC);
  case 4:
    return -9 * _HOUR_SEC;
  case 5:
  case 6:
    return -8 * _HOUR_SEC;
  case 7:
  case 8:
    return -7 * _HOUR_SEC;
  case 9:
  case 10:
    return -6 * _HOUR_SEC;
  case 11:
  case 12:
  case 13:
    return -5 * _HOUR_SEC;
  case 14:
    return -(4 * _HOUR_SEC + 30 * _MIN_SEC);
  case 15:
  case 16:
    return -4 * _HOUR_SEC;
  case 17:
    return -(3 * _HOUR_SEC + 30 * _MIN_SEC);
  case 18:
    return -3 * _HOUR_SEC;
  case 19:
    return -2 * _HOUR_SEC;
  case 20:
    return -1 * _HOUR_SEC;
  case 21:
  case 22:
    return 0;
  case 23:
  case 24:
  case 25:
    return 1 * _HOUR_SEC;
  case 26:
  case 27:
    return 2 * _HOUR_SEC;
  case 28:
  case 29:
    return 3 * _HOUR_SEC;
  case 30:
    return (3 * _HOUR_SEC + 30 * _MIN_SEC);
  case 31:
    return 4 * _HOUR_SEC;
  case 32:
    return (4 * _HOUR_SEC + 30 * _MIN_SEC);
  case 33:
    return 5 * _HOUR_SEC;
  case 34:
    return (5 * _HOUR_SEC + 30 * _MIN_SEC);
  case 35:
    return (5 * _HOUR_SEC + 45 * _MIN_SEC);
  case 36:
    return 6 * _HOUR_SEC;
  case 37:
    return (6 * _HOUR_SEC + 30 * _MIN_SEC);
  case 38:
    return 7 * _HOUR_SEC;
  case 39:
    return 8 * _HOUR_SEC;
  case 40:
    return 9 * _HOUR_SEC;
  case 41:
    return (9 * _HOUR_SEC + 30 * _MIN_SEC);
  case 42:
    return 10 * _HOUR_SEC;
  case 43:
    return (10 * _HOUR_SEC + 30 * _MIN_SEC);
  case 44:
    return 11 * _HOUR_SEC;
  case 45:
    return (11 * _HOUR_SEC + 30 * _MIN_SEC);
  case 46:
    return 12 * _HOUR_SEC;
  case 47:
    return (12 * _HOUR_SEC + 45 * _MIN_SEC);
  case 48:
    return 13 * _HOUR_SEC;
  case 49:
    return 14 * _HOUR_SEC;
  }
}


/***
*static time_t _make_time(time_rec, ultflag) -
*
*Purpose:
*       Converts a struct tm value to a time_t value, then updates the struct
*       tm value. Either local time or UTC is supported, based on ultflag.
*       This is the routine that actually does the work for both _mktime32() and
*       _mkgmtime32().
*
*Entry:
*       struct tm *time_rec - pointer to a tm time structure to convert and
*                             normalize
*       int ultflag         - use local time flag. the tb structure is assumed
*                             to represent a local date/time if ultflag > 0.
*                             otherwise, UTC is assumed.
*
*Exit:
*       If successful, _make_time returns the specified calender time encoded as
*       a time_t value. Otherwise, (time_t)(-1) is returned to
*       indicate an error.
*
*Exceptions:
*       None.
*
*Note :
*       Don't support DST in this version. and not strict param check.
*******************************************************************************/

static time_t _make_time(struct tm *time_rec, int ultflag){
  time_t tmptm1, tmptm2, tmptm3;
  struct tm tbtemp;
  
  if(time_rec == NULL)
    return (time_t)-1; 

  /*
   * First, make sure tm_year is reasonably close to being in range.
   */
  //if ( ((tmptm1 = time_rec->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1) )
  if ( ((tmptm1 = time_rec->tm_year) < _BASE_YEAR - 1))
      return (time_t)-1;


  /*
   * Adjust month value so it is in the range 0 - 11.  This is because
   * we don't know how many days are in months 12, 13, 14, etc.
   */

  if ( (time_rec->tm_mon < 0) || (time_rec->tm_mon > 11) ) {

      /*
       * no danger of overflow because the range check above.
       */
      tmptm1 += (time_rec->tm_mon / 12);

      if ( (time_rec->tm_mon %= 12) < 0 ) {
        time_rec->tm_mon += 12;
        tmptm1--;
      }

      /*
       * Make sure year count is still in range.
       */
      //if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1) )
    //return (time_t)-1;
  }

  /***** HERE: tmptm1 holds number of elapsed years *****/

  /*
   * Calculate days elapsed minus one, in the given year, to the given
   * month. Check for leap year and adjust if necessary.
   */
  tmptm2 = TimeExt_days[time_rec->tm_mon];
  if ( !(tmptm1 & 3) && (time_rec->tm_mon > 1) )
    tmptm2++;

  /*
   * Calculate elapsed days since base date (midnight, 1/1/70, UTC)
   *
   *
   * 365 days for each elapsed year since 1970, plus one more day for
   * each elapsed leap year. no danger of overflow because of the range
   * check (above) on tmptm1.
   */
  tmptm3 = (tmptm1 - _BASE_YEAR) * 365L + ((tmptm1 - 1L) >> 2)
    - _LEAP_YEAR_ADJUST;

  /*
   * elapsed days to current month (still no possible overflow)
   */
  tmptm3 += tmptm2;

  /*
   * elapsed days to current date. overflow is now possible.
   */
  tmptm1 = tmptm3 + (tmptm2 = (time_t)(time_rec->tm_mday));
  //if ( ChkAdd(tmptm1, tmptm3, tmptm2) )
  //    return (time_t)-1;

  /***** HERE: tmptm1 holds number of elapsed days *****/

  /*
   * Calculate elapsed hours since base date
   */
  tmptm2 = tmptm1 * 24L;
  if ( ChkMul(tmptm2, tmptm1, 24L) )
      return (time_t)-1;

  tmptm1 = tmptm2 + (tmptm3 = (time_t)time_rec->tm_hour);
  if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
      return (time_t)-1;

  /***** HERE: tmptm1 holds number of elapsed hours *****/

  /*
   * Calculate elapsed minutes since base date
   */

  tmptm2 = tmptm1 * 60L;
  if ( ChkMul(tmptm2, tmptm1, 60L) )
      return (time_t)-1;

  tmptm1 = tmptm2 + (tmptm3 = (time_t)time_rec->tm_min);
  if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
      return (time_t)-1;

  /***** HERE: tmptm1 holds number of elapsed minutes *****/

  /*
   * Calculate elapsed seconds since base date
   */

  tmptm2 = tmptm1 * 60L;
  if ( ChkMul(tmptm2, tmptm1, 60L) )
      return (time_t)-1;

  tmptm1 = tmptm2 + (tmptm3 = (time_t)time_rec->tm_sec);
  if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
      return (time_t)-1;

  /***** HERE: tmptm1 holds number of elapsed seconds *****/

  if  ( ultflag ) {

      /*
       * Adjust for timezone. No need to check for overflow since
       * localtime() will check its arg value
       */

      //__tzset();

      //_ERRCHECK(_get_dstbias(&dstbias));

      tmptm1 -= getTimezoneOffset();

      /*
       * Convert this second count back into a time block structure.
       * If localtime returns NULL, return an error.
       */
      //if ( _localtime32_s(&tbtemp, &tmptm1) != 0 )
       // return (time_t)-1;
      TimeExt_localtime(&tbtemp, &tmptm1);

      /*
       * Now must compensate for DST. The ANSI rules are to use the
       * passed-in tm_isdst flag if it is non-negative. Otherwise,
       * compute if DST applies. Recall that tbtemp has the time without
       * DST compensation, but has set tm_isdst correctly.
       */
      //if ( (time_rec->tm_isdst > 0) || ((time_rec->tm_isdst < 0) &&
      //  (tbtemp.tm_isdst > 0)) ) {
    //tmptm1 += dstbias;
    //if ( _localtime32_s(&tbtemp, &tmptm1) != 0 )
    //    return (time_t)-1;
    //  }

  }else {
    //if ( _gmtime32_s(&tbtemp, &tmptm1) != 0 )
    //return (time_t)-1;
    TimeExt_gmtime(&tbtemp, &tmptm1);
  }

  /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/
  /*****       for local time if requested          *****/

  *time_rec = tbtemp;
  return tmptm1;
}

使用

PUBLIC INTERFACES部分就不说了,就按标准库的用法来用就好。

然后问题就是,肯定要有方法告诉这个模块当前时间的流逝。
当前实现要求每隔1ms调用一次

TimeExt_clocktick()

请开启一个1ms的中断,在其中调用它。

然后肯定要有一个授时接口,当你通过某种方法获得当前的时间后,通过

void TimeExt_setgmtime(const time_t *time_val, uint32_t us);

进行授时就好。

另外有一个小的注意点,标准库很多接口在出错时都会返回-1,但是由于CodeWarrior中time_t是无符号类型的,所以你要是写
XXXX == -1
的话则可能被编译器认为必为FALSE。为了避免这个问题,判断是否出错时写成
XXXX == (time_t)(-1)
就一定没有问题了。

更新历史

2019/10/18 V1.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值