根據毫秒數計算出準確的“年/月/日/時/分/秒/星期”並不是件容易的事

鍾超發表於2012-04-04

根據毫秒數計算出當前的“年/月/日/時/分/秒/星期”並不是件容易的事

  • 作者:鍾超
  • 部落格:柳大·PoechantBlog.CSDN.net
  • 日期:April 4th, 2012

下文中會用到一些公式,比如:empirical formulaGauss' formula等。主要思想取自 Nginx 的時間管理機制中。

1 毫秒、秒、分、時

如果已知毫秒數為:

unsigned int msec_total;

那麼秒數和餘毫秒數為:

unsigned int sec_total = msec_total /  1000;
unsigned int msec = msec_total % 1000; /* What we want */

分鐘數和餘秒數為:

unsigned int min_total = sec_total / 60;
unsigned int sec = sec_total % 60;

小時數和餘分鐘數為:

unsigned int hour_total = min_total / 60;
unsigned int min = min_total % 60;

餘小時數為:

unsigned int hour = hour_total % 24;

剩下的內容非常重要。

2 總天數

unsigned int day_total = hour_total / 24;
day_total = day_total - (31 + 28) + 719527; /* days since March 1, 1 BC */

3 年數

什麼是閏年?有如下幾類:

  • 能被4整除,但不能被100整除;
  • 能被400整除。

所以總年數是:

/* 總年數 */
year = (days + 2) * 400 / (365 * 400 + 100 - 4 + 1);

還要繼續知道整年的余天:

/* yday是整年的余天 */
yday = days - (365 * year + year / 4 - year / 100 + year / 400);

/* 如果余天小於0,說明年數應該減一 */
if (yday < 0) {
    /* 可以被4整除,且不可以被100整除,且可以被400整除 */
    leap = (year % 4 == 0) && (year % 100 || (year % 400 == 0));
    /* 加當年的年數補差值 */
    yday = 365 + leap + yday;
    year--;
}

具體的解釋看註釋。

4 月份和日期

轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net

這裡用到empirical formulaGauss' formula

/*
 * The empirical formula that maps "yday" to month.
 * There are at least 10 variants, some of them are:
 *     mon = (yday + 31) * 15 / 459
 *     mon = (yday + 31) * 17 / 520
 *     mon = (yday + 31) * 20 / 612
 */

/* 30.6 為平均每月天數 */
mon = (yday + 31) * 10 / 306;

/* the Gauss' formula that evaluates days before the month */

mday = yday - (367 * mon / 12 - 30) + 1;

if (yday >= 306) {

    year++;
    mon -= 10;

    /*
     * there is no "yday" in Win32 SYSTEMTIME
     *
     * yday -= 306;
     */

} else {

    mon += 2;

    /*
     * there is no "yday" in Win32 SYSTEMTIME
     *
     * yday += 31 + 28 + leap;
     */
}

5 星期

wday = (4 + days) % 7; /* 今兒是星期幾?注意,1970年1年1日為星期四 */

6 整理日期

msec; /* 毫秒 */
sec;  /* 秒 */
min;  /* 分 */
hour; /* 小時 */
mday; /* 日 */
mon;  /* 月 */
year; /* 年 */
wday; /* 星期 */

7 後記

7.1 將閏秒寫入計算機的時間計算方法?

閏秒是人為加入的,計算機中如何表示?什麼時候插入閏秒,是由人來決定的,只不過原因是可探究的,但依然無法用公式或程式來計算。

7.2 誰決定是否加入閏秒?

是否加入閏秒由位於巴黎的國際地球自轉和參考座標系統服務決定,在格里曆的每年的6月或12月的最後一天的最後一分鐘進行跳秒或不跳秒,也就是說每年的這兩個一分鐘並不就是等於60秒,而是在60秒上下變化。

7.3 停止閏秒的表決(以下摘自中文維基)

全球定位系統服務介面委員會在得克薩斯州沃斯堡舉行的第47屆會議中宣佈,他們已經郵寄出停止閏秒的表決案。這項表決案的計劃是[1]:

  • 2008年4月:國際電信聯盟的工作小組將遞交給研究小組關於勸說停止閏秒的7A建議專案。
  • 在2008年,研究小組將通過經由郵件讓各會員國投票表決該議案。
  • 2011年:如果70%以上的會員國同意,國際電信會議將批准該建議案。
  • 2013年:如果70%以上的會員國投票廢止閏秒,閏秒將停止使用,並且世界時(UTC)將成為連續的時間刻度尺。

-

轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net

-

相關文章