作者Dopin (ats.twbbs.org)
站内SetupBBS
标题<转录/Local Save> 三篇关於 date_stamp 实作
时间Tue Jan 12 12:56:28 2010
转录到这之後附注说明 :
(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:
[email protected]
%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