看板 SetupBBS 關於我們 聯絡資訊
轉錄到這之後附註說明 : (1) 因為文章不見 有人寫信予我這裡看比較方便 ... (其實我覺得到出處看就好 ...) (2) 以往 我們都是用 time_t now = time(NULL); 取得 timestamp 後用 ctime() 去 秀出 YYYY MM DD hh rr ss (格式看用那個函式 也有自訂函式) 可是我們無法用 YYYY MM DD (本程式以 day 為基準省略 hh mm <即只以第一天的第 0 小時 0 分 為算出值 本程式 當然 可擴充 再輸入 時(hh) 分(mm) 秒(ss)> 於此略之) #include <stdio.h> #include <time.h> int main(void) { time_t now = time(NULL); printf("%d\n%s\n", (int)now, ctime(&now)); return 0; } 我們如果得到一個 stamp 值 1263225600 代入 ctime() 即可顯示我們所知的時制 : #include <stdio.h> #include <time.h> int main(void) { time_t now = 1263225600; printf("%s\n", ctime(&now)); return 0; } 會得到這樣的結果 : Tue Jan 12 00:00:00 2010 我們要算 2010/01/15 00:00:00 的 timestamp 怎算 ? 很簡單 把 2010/01/12 的 timestamp 加上 86400x3 即可 加減都可以比照 但是 ... 那 我們有沒有辦法輸入 2010 01 12 然後得到 stamp 值呢 ? 很遺憾的 在 ANSI-C 中 並沒有 這樣的東西 有人或許會問了 要這種東西做啥 ? 最簡單的問題應用 -> 求 A B 兩時間點差了多久 "民國 96 年 11 月 16 日" 跟 "民國 85 年 11 月 16 日" 差了幾天 ? 這問題很單純 他們差了11 年 那 11 年是差幾天 ? 365x11 ? 不是吧 ... 原因很 簡單 閏年問題 所以我們計算時要加上 '中間經過幾個閏年' 好 這可能還是個簡單的問題 那麼來點比較長的時間 "民國 97 年 03 月 02 日" 跟 "民國 68 年 05 月 16 日" 差了幾天 ? 算出 多一年的 3/02 跟 5/16 差幾天 再乘以不足年數 x365 天 再加閏年有幾個 很好 如果每個日期都這樣比對 即時運算會很 ... 我想大家知道我的意思 ... 又有人會說 阿就 difftime() 套下去就好啦 ? 可是 ... 有這麼簡單嗎 ? 來看原式宣告 double difftime(time_t time1, time_t time0); time_t 可是 integer 喔 可不是啥 [CC]YY/MM/DD 這麼單純 如我有這種東西我 也想用 (其實 有個秘密 ... 懂 本程式 你可以自己寫一個 int diff_date(char *date1, char *date2); // date 1/2 as yyyy/mm/dd 到時就可這樣叫用 diff_date("2009/12/18", "1997/12/19"); (這兩個日期的梗相信鄉民知道 :p) 簡而言之 沒有真的實作過人的不會知道 "沒有可用函式" 的心酸 :p 所以 我這篇文章其實是把行之有年的東東 公開 來 !!! 如果 還不知道這個函式有 ~多麼好用~ 看倌們就當作是看看小學數學習題亦可 :) X X X 作者 Dopin (系統調校完成) 看板 InstallBBS 標題 <轉錄> 受不了 ... 時間 Wed Dec 16 23:16:06 2009 ─────────────────────────────────────── ※ [本文轉錄自 ATSVersion 看板] 作者: Dopin (系統調校完成) 看板: ATSVersion 標題: 受不了 ... 時間: Wed Dec 16 06:17:21 2009 想說要把自動連署寫的更完備些 舊程式遇到跨年就死了 - -;;; 所以我想找個能把 yyyy/dd/mm 轉成 timestamp 的程式 這樣純數值減法問題會少很多 不用啥比月份 大小完再比日期 遇到年份不同再比 ... 囉唆的要命 Orz 我依稀這玩意兒國中還高中讀書時代寫過 (那時是賺外快幫個漫畫店寫 Clipper 遇 到沒有 yyyymmdd 的好用解 而 DBASE 內建的東西又爛的要死 所以 "開發的" (扛 成 .obj 拿來 link 用 Orz) 不幸的是以前的實作法真的給他忘記了 ... 我只記得有用到 difftime() 之類函式 (也許有記錯 我記得是 Turbo C 下寫的) 但實在想不起來程式片段的詳細到底是怎 樣 而且那時就愛耍帥 喜歡把程式寫的讓人看不懂 最後 ... 看不懂的往往是自己 (還喜歡在 C 裡 inline ASM - -;;;) 人懶 沒藥醫 上網找有沒有現成的函式可以用 (不要臉 :p) 但是 !!! 找半天沒找著 (怒) 只找到個網站有類似討論的 : http://www.lslnet.com/linux/f/docs1/i41/big5291280.htm (再次強調 我是要找 ANSI-C 的解法) 但是進去看發現不是寫的亂七八糟 就是根本 寫錯 而且 還有人居然對其他討論者這樣寫道 : "特大喜訊,我給你發了. 公司機密文件,僅限站內朋友,請勿外傳,謝謝." 或是什麼 "不過不要敲我的飯碗啊." "收到,謝謝,不敢外傳!" 都可以說 ... 我的天 這又不是啥偉大或獨門的演算法 :p 不過熱心助人是不能否定的 能用當然是歡樂 ^OO^ 無奈 ... 略 "喵" 了該網頁的範 例 兩個都寫的亂七八糟(第三個只是把時間函式列出來 <核爆>) 看到那種縮排 我自 己搞都比較快 所以啦 就這樣辦 = =b (GOGOGOGO !!!) 說嘴 : 下面那篇文章的程式 "完全不是" 啥了不起的東西 不過要是拿去用可要說 這是 Dopin 的解法 (再次不要臉 XD ... 冷掉了) -- Origin: Atlantis DN: bbs.bsd.com.tw IP : 203.70.65.27 ST: atlantis X X X 作者 Dopin (系統調校完成) 看板 InstallBBS 標題 <轉錄> src/maple/date_stamp.c (拿到 maple/ 下扛最快 :p) 時間 Wed Dec 16 23:16:16 2009 ─────────────────────────────────────── ※ [本文轉錄自 ATSVersion 看板] 作者: Dopin (系統調校完成) 看板: ATSVersion 標題: src/maple/date_stamp.c (拿到 maple/ 下扛最快 :p) 時間: Wed Dec 16 06:26:15 2009 /*-------------------------------------------------------*/ /* date_stamp.c ( Atlantis BBS Ver 1.32 ) */ /*-------------------------------------------------------*/ /* target : 將 yyyy mm dd 的引數轉換成 time stamp */ /* create : 2009/12/16 (Dopin) */ /* update : / / */ /*-------------------------------------------------------*/ /* syntex : date_stamp <yyyy> <mm> <dd> */ /*-------------------------------------------------------*/ #include "bbs.h" // ats 1.32 append 小學例題 計算閏年 我還故意用很 "易懂" 的回傳法 :p int check_bissextile(int y) { /* 逢 四年 閏 逢 百年 不閏 逢 百年 且 逢 四百年 又閏 */ return !(y % 4) && ((y % 100) || !(y % 100) && !(y % 400)) ; } // ats 1.32 append 小學例題 判定年月日是否合理 本程式不考慮 1970 年前 // 也缺乏詳細的每月檢查(只查閏月)有需要嚴格檢查自己改 int chack_yyyymmdd(int y, int m, int d) { if(y < 1970) return -1; if(m > 12 || m < 1) return -2; if(d > 31 || d < 1) return -3; if(m == 2 && (check_bissextile(y) && d > 29 || !check_bissextile(y) && d > 28)) return -4; return 0; } // ats 1.32 append 計算 yyyymmdd 的 timestamp 究極土法鍊鋼 才是王道 (挺) int yyyymmdd_to_stamp(int y, int m, int d) { char day[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 0 }; int i, days = 0; /* 沒人需要 12 月 除非整年要從一加到十二月 ! */ // 加到前一年 for(i = 1970 ; i < y ; i++) days += check_bissextile(i) ? 366 : 365; // 加到前一月 for(i = 1 ; i < m ; i++) days += day[i - 1]; // 加到當天 days += d; // 該年為閏年且超過 二月 (因為閏月格式先前已檢查過) 加一天 if(check_bissextile(y) && m > 2) days += 1; // 多減一天的原因是 1970 年的 1 月 1 號 是 0 所以含了當天會 "多算一天" // 多減 8 小時的原因是因為我們用 GMT 跟 CST 差八小時 隨時區不同要調整 return days * 86400 - 86400 - 8 * 3600 ; } /* 以上的函式 我會加到之後的 dopin.c / dopin.h 之中 這程式沒有 Y2K 問題 */ int main(int argc, char *argv[]) { int y, m, d, error; time_t stamp; if(argc != 4) { puts("syntex: date_stamp <yyyy> <mm> <dd>"); return -1; } y = atoi(argv[1]); m = atoi(argv[2]); d = atoi(argv[3]); if(error = chack_yyyymmdd(y, m, d)) { printf("date error ! Code : %d\n", error); return -2; } stamp = (time_t)yyyymmdd_to_stamp(y, m, d); printf("[ %d ]\n", (int)stamp); /* 這行純驗證用 覺得不需要就可以拿掉他 */ printf("%s", ctime(&stamp)); return 0; } -- Origin: Atlantis DN: bbs.bsd.com.tw IP : 203.70.65.27 ST: atlantis X X X 作者 Dopin (系統調校完成) 看板 InstallBBS 標題 <轉錄> Re: src/maple/date_stamp.c (拿到 maple/ 下扛最快 … 時間 Wed Dec 16 23:16:27 2009 ─────────────────────────────────────── ※ [本文轉錄自 ATSVersion 看板] 作者: Dopin (系統調校完成) 看板: ATSVersion 標題: Re: src/maple/date_stamp.c (拿到 maple/ 下扛最快 … 時間: Wed Dec 16 06:32:33 2009 In-Reply-To: 4jPOQe$lG_@bbs.bsd.com.tw %make date_stamp gcc -O2 -I../include date_stamp.c -o date_stamp %./date_stamp 1983 02 27 [ 415123200 ] Sun Feb 27 00:00:00 1983 %./date_stamp 2009 12 16 [ 1260892800 ] Wed Dec 16 00:00:00 2009 %./date_stamp 2004 2 29 [ 1077984000 ] Sun Feb 29 00:00:00 2004 %./date_stamp 1970 1 1 [ -28800 ] Thu Jan 1 00:00:00 1970 % 所以用法簡單易懂 科科 特別注意您所使用的伺服器時間 如果有錯誤 記得要調整時區 或是把那個 - 8 * 3600 給拿掉 才能正確算出數值 最後 因為 signed int (32bits) 的極值問題 這個程式的最高極限日 期數值 是 2147443200 也就是 2038/01/19 超過就會出鎚 :p 真的想 要做點限制避免算錯 在比對日期格式的函式部份再動點手腳就好 最後實際用到應用上 比方要計算 2006/01/13 與 1986/12/07 差了幾 天 只要各自求出 stamp 數值 彼此相減後再除以秒數即可 如果真的只 需要算差幾天就夠了 86400 部份修改掉就好 [本程式範例皆以 32bits 環境為基準] -- Origin: Atlantis DN: bbs.bsd.com.tw IP : 203.70.65.27 ST: atlantis -- SOB Pack 已於日前 Release 出 gcc 4.x 版, 歡迎還活在 Maple 2.36 SOB Version 回憶中的朋友們一起來討論下列相關 : 1. maple 2.36 2. SOB 3. Atlantis Version telnet to bbs.bsd.com.tw Boardname : ATSVersion -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 203.70.65.27