亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > .NET > 正文

C標準庫源碼解剖(8):日期與時間函數time.h(續)

2024-07-10 13:27:17
字體:
來源:轉載
供稿:網友

4、difftime函數:從日歷時間t1中減去日歷時間t0,返回double類型的差值(秒數)。

 

[cpp] view plaincopy
  1. /* difftime.c:difftime函數的實現 */  
  2. #include <time.h>  
  3. #include <limits.h>  
  4. #include <float.h>  
  5. #include <stdint.h>  
  6. #define TYPE_BITS(type) (sizeof (type) * CHAR_BIT)  
  7. #define TYPE_FLOATING(type) ((type) 0.5 == 0.5)  
  8. #define TYPE_SIGNED(type) ((type) -1 < 0)  
  9. /* 返回兩個時間TIME1和TIME0的差值(秒數),這里TIME0<=TIME1,time_t眾所周知是 
  10.     一個整數類型 */  
  11. static double  
  12. subtract (time_t time1, time_t time0)  
  13. {  
  14.   if (! TYPE_SIGNED (time_t))  
  15.     return time1 - time0;  
  16.   else  
  17.     {  
  18.       /* 對一般的情況進行優化,這里time_t能無損地轉換成uintmax_t */  
  19.       uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0;  
  20.       double delta = dt;  
  21.       if (UINTMAX_MAX / 2 < INTMAX_MAX)  
  22.     {  
  23.       /* 這是一種罕見的情況,uintmax_t有填充位,當把time_t轉換成uintmax_t時可能會丟失信息。 
  24.           通過比較dt/2與(time1/2-time0/2)檢查是否有溢出,如果它們有一個小的差值,則發生溢出 
  25.            
  26.           在下面的代碼中,"h"前綴表示一半(half),通過范圍分析,我們有: 
  27.                   -0.5 <= ht1 - 0.5*time1 <= 0.5 
  28.                   -0.5 <= ht0 - 0.5*time0 <= 0.5 
  29.                   -1.0 <= dht - 0.5*(time1 - time0) <= 1.0 
  30.                 如果溢出沒有發生,我們也有: 
  31.                   -0.5 <= hdt - 0.5*(time1 - time0) <= 0 
  32.                   -1.0 <= dht - hdt <= 1.5 
  33.                 并且因為dht-hdt是一個整數,我們有: 
  34.                   -1 <= dht - hdt <= 1 
  35.                 或者等價的有: 
  36.                   0 <= dht - hdt + 1 <= 2 
  37.                 在上面的分析中,所有的運算符都有它們準確的數學語義,而不是C語義。然而, 
  38.              dht-hdt+1在C中是無符號的,因此它無需與0比較  */  
  39.       uintmax_t hdt = dt / 2;  
  40.       time_t ht1 = time1 / 2;  
  41.       time_t ht0 = time0 / 2;  
  42.       time_t dht = ht1 - ht0;  
  43.       if (2 < dht - hdt + 1)  
  44.         {  
  45.           /* 修復這個微小的溢出 
  46.              下面的表達式包含一個秒數的舍入,因此結果可能不是與真正答案最接近的。這種 
  47.              情況只在差值非常大時發生 */  
  48.           delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2);  
  49.         }  
  50.     }  
  51.       return delta;  
  52.     }  
  53. }  
  54. /* 返回TIME1和TIME0之間的差值(秒數)  */  
  55. double  
  56. __difftime (time_t time1, time_t time0)  
  57. {  
  58.   /* 如果不會導致double的舍入錯誤,就轉換成double類型,然后做減法 */  
  59.   if (TYPE_BITS (time_t) <= DBL_MANT_DIG  
  60.       || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double)))  
  61.     return (double) time1 - (double) time0;  
  62.   /* 對long double做同樣的事  */  
  63.   if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t))  
  64.     return (long double) time1 - (long double) time0;  
  65.   /* 調用substract從大的參數中減去小的整數,把差值轉換成double,如果需要還要轉換成負數  */  
  66.   return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);  
  67. }  
  68. /* 把函數命名為標準的difftime */  
  69. strong_alias (__difftime, difftime)  

 

    由于time_t是整型,因此代碼中如果不會導致double的舍入錯誤,就轉換成double類型,然后做減法。如果有可能導致double的舍入錯誤,則調用substract做減法。substract中,把兩個time_t參數轉換成最大長度的整數類型uintmax_t,一般都能實現無損的轉換,然后做減法,返回結果值。有一種罕見的情況即UINTMAX_MAX / 2 < INTMAX_MAX時,會導致轉換有微小的溢出,因此對這種情況要進行特殊地處理,這時獲得的結果可能是真正答案的近似值(有一個細微的舍入)。 
    5、gmtime,localtime,mktime:gmtime把time_t類型時間值轉換成UTC中的struct tm表示,localtime把time_t類型時間值轉換成本地時間區域中的struct tm表示,mktime根據struct tm結構指定的本地時間構造time_t類型的值。mktime由于要對tm結構的各個成員值進行分析,然后合并成time_t類型的值返回,比較復雜,代碼就不解剖了。而且不同Linux/Unix平臺上的實現有差異,需要兼容不同的平臺。核心的函數是__mktime_internal,在mktime中只是直接調用這個函數。gmtime和localtime的實現比較簡單,都是直接調用內置函數__tz_convert來完成工作,如下:

 

[cpp] view plaincopy
  1. /* gmtime.c:gmtime函數的實現,把`time_t'轉換成UTC中的`struct tm'  */  
  2. #include <time.h>  
  3. /* 返回TIMER的struct tm表示(為格林尼治標準時間UTC), 
  4.     使用TP來存放結果 */  
  5. struct tm *  
  6. __gmtime_r (t, tp)  
  7.      const time_t *t;  
  8.      struct tm *tp;  
  9. {  
  10.   return __tz_convert (t, 0, tp);  
  11. }  
  12. libc_hidden_def (__gmtime_r)  
  13. weak_alias (__gmtime_r, gmtime_r)  
  14. /* 返回TIMER的struct tm表示(為格林尼治標準時間UTC) */  
  15. struct tm *  
  16. gmtime (t)  
  17.      const time_t *t;  
  18. {  
  19.   return __tz_convert (t, 0, &_tmbuf);  
  20. }  

 

 

[cpp] view plaincopy
  1. /* localtime.c:localtime函數的實現,把`time_t'轉換成本時間區域中的`struct tm'  */  
  2. #include <time.h>  
  3. /* C標準指出localtime和gmtime返回同樣的指針  */  
  4. struct tm _tmbuf;  
  5. /* 返回TIMER的struct tm表示(為本地時間),使用TP來存放結果 */  
  6. struct tm *  
  7. __localtime_r (t, tp)  
  8.      const time_t *t;  
  9.      struct tm *tp;  
  10. {  
  11.   return __tz_convert (t, 1, tp);  
  12. }  
  13. weak_alias (__localtime_r, localtime_r)  
  14.   
  15. /* 返回T的struct tm表示(為本地時間) */  
  16. struct tm *  
  17. localtime (t)  
  18.      const time_t *t;  
  19. {  
  20.   return __tz_convert (t, 1, &_tmbuf);  
  21. }  
  22. libc_hidden_def (localtime)  

 

    6、asctime,ctime:asctime返回tp時間(struct tm結構)的可打印格式,格式為"%a %b %d %H:%M:%S %Y/n",ctime(time_t *tp)等價于asctime(localtime(tp))。

 

[cpp] view plaincopy
  1. /* asctime.c:asctime函數的實現 */  
  2. #include "../locale/localeinfo.h"  
  3. #include <errno.h>  
  4. #include <limits.h>  
  5. #include <stdio.h>  
  6. #include <time.h>  
  7. /* 這里的函數在GNU libc的locale/C-time.c中定義  */  
  8. extern const struct locale_data _nl_C_LC_TIME attribute_hidden;  
  9. #define ab_day_name(DAY) (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)+(DAY)].string)  
  10. #define ab_month_name(MON) (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)+(MON)].string)  
  11. static const char format[] = "%.3s %.3s%3d %.2d:%.2d:%.2d %d/n";  
  12. static char result[          3+1+ 3+1+20+1+20+1+20+1+20+1+20+1 + 1];  
  13. /* 輸出日歷時間的核心函數 */  
  14. static char *  
  15. asctime_internal (const struct tm *tp, char *buf, size_t buflen)  
  16. {  
  17.   if (tp == NULL)  
  18.     {  
  19.       __set_errno (EINVAL); /* 參數無效的錯誤 */  
  20.       return NULL;  
  21.     }  
  22.   /* 我們限制打印的年份大小。使用%d格式說明符表示年份后兩位(即要加上1900),這可能溢出 
  23.        使得一個負值被打印出來。對一些體系結構而言,我們在理論上能使用%ld或者更大的整數格 
  24.        式,但這將意味著輸出需要更大的空間。如果asctime_r接口比較健壯,并且傳遞給它一個 
  25.        緩沖區,那么這將不再是問題 */  
  26.   if (__builtin_expect (tp->tm_year > INT_MAX - 1900, 0)) /* 使用了內部的一個斷言 */  
  27.     {  
  28.     eoverflow:  
  29.       __set_errno (EOVERFLOW); /* 設置溢出錯誤 */  
  30.       return NULL;  
  31.     }  
  32.   /* 按格式"Day Mon dd hh:mm:ss yyyy/n"打印給定的日歷時間 */  
  33.   int n = __snprintf (buf, buflen, format,  
  34.               (tp->tm_wday < 0 || tp->tm_wday >= 7 ?  
  35.                "???" : ab_day_name (tp->tm_wday)),  
  36.               (tp->tm_mon < 0 || tp->tm_mon >= 12 ?  
  37.                "???" : ab_month_name (tp->tm_mon)),  
  38.               tp->tm_mday, tp->tm_hour, tp->tm_min,  
  39.               tp->tm_sec, 1900 + tp->tm_year);  
  40.   if (n < 0)  
  41.     return NULL;  
  42.   if (n >= buflen)  
  43.     goto eoverflow; /* 轉身上面的eoverflow標號處 */  
  44.   return buf;  
  45. }  
  46. /* 與asctime類似,但把結果寫入到顯式提供的緩沖區中。這個緩沖區只保證使用前26字節 
  47.     的長度 */  
  48. char *  
  49. __asctime_r (const struct tm *tp, char *buf)  
  50. {  
  51.   return asctime_internal (tp, buf, 26);  
  52. }  
  53. weak_alias (__asctime_r, asctime_r)  
  54.   
  55. /* 返回表示TP的可打印日期與時間字符串,格式為"Day Mon dd hh:mm:ss yyyy/n" */  
  56. char *  
  57. asctime (const struct tm *tp)  
  58. {  
  59.   return asctime_internal (tp, result, sizeof (result));  
  60. }  
  61. libc_hidden_def (asctime)  

 

 

[cpp] view plaincopy
  1. /* ctime.c:ctime函數的實現  */  
  2. #undef  __OPTIMIZE__    /* 避免內聯ctime函數  */  
  3. #include <time.h>  
  4. #undef  ctime  
  5. /* 返回像asctime中一樣的表示時間T的字符串,等價于asctime(localtime (t)) */  
  6. char *  
  7. ctime (const time_t *t)  
  8. {  
  9.   /* C標準指出ctime(t)等價于asctime(localtime(t)),特別地,ctime和asctime必須 
  10.       生成同樣的指針 */  
  11.   return asctime (localtime (t));  
  12. }  

 

    asctime_internal是實現日歷時間輸出的核心函數。這里限制了打印的年份大小,以防年份太大而溢出,然后調用內部函數__snprintf來把時間輸出到全局的字符串result中,并返回這個字符串,格式控制字符串保存在全局的format串中。    
    7、strftime,wcsftime:對struct tm結構的時間進行格式化輸出,保存到字符串中。strftime函數根據控制串FORMAT對TP進行格式化,并保存到字符串S中,最多寫入MAXSIZE個字符到S中,并返回寫入的字符數,如果字符串長超過MAXSIZE,則返回0。wcsftime是對應的寬字符版本,時間會被格式化成寬字符串,在wchar.h中聲明。它們都直接調用內部函數__strftime_l和__wcsftime_l來完成工作。

 

[cpp] view plaincopy
  1. /* strftime.c:strftime函數的實現  */  
  2. #include <time.h>  
  3. #include <locale/localeinfo.h>  
  4. /* 根據控制串FORMAT對TP進行格式化,并保存到字符串S中,最多寫入MAXSIZE個字符到S中, 
  5.     并返回寫入的字符數,如果字符串長超過MAXSIZE,則返回0 */  
  6. size_t  
  7. strftime (char *s, size_t maxsize, const char *format, const struct tm *tp)  
  8. {  
  9.   return __strftime_l (s, maxsize, format, tp, _NL_CURRENT_LOCALE);  
  10. }  
  11. libc_hidden_def (strftime)  

 

 

[cpp] view plaincopy
  1. /* wcsftime.c:wcsftime函數的實現  */  
  2. #include <wchar.h>  
  3. #include <locale/localeinfo.h>  
  4. /* 根據控制串FORMAT對TP進行格式化,并保存到寬字符串S中,最多寫入MAXSIZE個字符到S中, 
  5.     并返回寫入的字符數,如果字符串長超過MAXSIZE,則返回0 */  
  6. size_t  
  7. wcsftime (wchar_t *s, size_t maxsize, const wchar_t *format,  
  8.       const struct tm *tp)  
  9. {  
  10.   return __wcsftime_l (s, maxsize, format, tp, _NL_CURRENT_LOCALE);  
  11. }  
  12. libc_hidden_def (wcsftime)  

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品电影久久久久电影网| 欧美插天视频在线播放| 国产精品美女网站| 日韩高清av在线| 欧美激情免费在线| 日韩成人小视频| 欧美成人四级hd版| 在线播放精品一区二区三区| 亚洲欧洲第一视频| 国内外成人免费激情在线视频| 国产精品视频永久免费播放| 国产亚洲欧美日韩美女| 亚洲伊人第一页| 久久久久亚洲精品国产| 欧美日韩黄色大片| 精品动漫一区二区三区| 欧美大片大片在线播放| 2019精品视频| 北条麻妃久久精品| 青青精品视频播放| 欧美亚洲伦理www| 日韩欧美亚洲综合| 国产日韩在线视频| 久久免费视频这里只有精品| 国产精品福利无圣光在线一区| 国产成人中文字幕| 成人国产精品一区二区| 亚洲激情电影中文字幕| 亚洲小视频在线观看| 国产精品18久久久久久首页狼| 国产精品色婷婷视频| 日韩不卡在线观看| 黄网站色欧美视频| 国产日韩欧美视频| www.日韩视频| 久久精品视频播放| 国产精品久久久久久久久久久久久久| 午夜精品久久久久久久99热| 精品久久久久久久久久国产| 亚洲精品不卡在线| 国产精品丝袜久久久久久不卡| 国产精品入口免费视| 欧美国产精品va在线观看| 国产一区二区三区在线免费观看| 日韩av观看网址| 91色p视频在线| 日韩中文字幕在线观看| 日韩av一区在线| 国产日韩欧美中文在线播放| 在线精品视频视频中文字幕| 久久精品国产亚洲7777| 国产九九精品视频| 亚洲偷熟乱区亚洲香蕉av| 亚洲电影第1页| 亚洲美女精品久久| 在线成人一区二区| 日韩视频亚洲视频| 欧美黑人狂野猛交老妇| 欧美另类在线观看| 欧美一级片在线播放| 久久久999精品视频| 97在线视频免费看| 日韩欧美黄色动漫| 97成人精品区在线播放| 午夜精品一区二区三区在线播放| 亚洲理论片在线观看| 亚洲女人天堂av| 国内外成人免费激情在线视频| 欧美日产国产成人免费图片| 国产欧亚日韩视频| 亚洲亚裔videos黑人hd| www.欧美免费| 精品日本美女福利在线观看| 欧美激情中文字幕在线| 国产不卡精品视男人的天堂| 日韩美女写真福利在线观看| 国产精品大片wwwwww| 九九视频直播综合网| 国产精品久久久久久久av电影| 午夜精品久久久久久久男人的天堂| 992tv成人免费影院| 亚洲影院色在线观看免费| 91免费国产网站| 国产精品嫩草影院久久久| 一本色道久久88亚洲综合88| 亚洲一区二区精品| 国产精品久久久久久久久男| 亚洲少妇中文在线| 一二美女精品欧洲| 欧美成人久久久| 国产精品久久国产精品99gif| 免费91麻豆精品国产自产在线观看| 欧美黑人国产人伦爽爽爽| 久久人91精品久久久久久不卡| 国产精品一区二区在线| 国产精品亚洲第一区| 日韩国产精品亚洲а∨天堂免| 亚洲国产又黄又爽女人高潮的| 国产亚洲精品美女久久久久| 成人精品在线视频| 精品久久久久久中文字幕| 在线精品高清中文字幕| 国产一区二区三区精品久久久| 久久成人av网站| 91久久综合亚洲鲁鲁五月天| 亚洲人成电影在线观看天堂色| 91午夜理伦私人影院| 亚洲精品日韩欧美| 97av在线播放| 久久精品青青大伊人av| 国内精品中文字幕| 国产成人免费av| 欧美高清理论片| 欧美在线一区二区三区四| 欧美贵妇videos办公室| 欧美午夜视频一区二区| 亚洲成色www8888| 亚洲天堂免费视频| 国产精品丝袜视频| 国产91色在线| 成人国产精品色哟哟| 一区二区中文字幕| 欧美裸身视频免费观看| 一个人看的www欧美| 日韩中文字幕国产| 国产91色在线|免| 少妇高潮久久久久久潘金莲| 不卡毛片在线看| 在线视频日韩精品| 日韩高清有码在线| 8x拔播拔播x8国产精品| 欧美日韩999| 亚洲欧美一区二区三区情侣bbw| 久久久久久久久久久av| 色av中文字幕一区| 中文字幕一区二区精品| 热久久99这里有精品| 日韩高清a**址| 久久久精品久久久| 亚洲加勒比久久88色综合| 亚洲天堂免费观看| 成人免费视频97| 在线中文字幕日韩| y97精品国产97久久久久久| 欧美另类暴力丝袜| 国产亚洲激情在线| 亚洲欧美日韩中文视频| 欧美黑人巨大xxx极品| 国产日本欧美在线观看| 久久久精品2019中文字幕神马| 午夜精品在线视频| 国产日韩欧美影视| 亚洲精品美女久久久| 欧美做爰性生交视频| 欧美在线视频播放| 26uuu日韩精品一区二区| 欧美日韩在线看| 中文字幕日韩高清| 欧美激情中文网| 亚洲一区美女视频在线观看免费| 性视频1819p久久| 欧美亚洲一区在线| 国产在线日韩在线| 国产成人小视频在线观看|