2011-08-21 35 views

回答

3

沒有簡單的公式來做到這一點。你將需要減去自紀元以來的年數(佔閏年),這可能需要循環或某種離散計算。然後使用某種類型的循環來減去當年每月的秒數。剩下的是當前進入月份的秒數。

我會做這樣的事情。

x = ...//the number of seconds 
year = 1970 

while (x > /*one year*/){ 
x = x - /*seconds in january, and march-december*/ 
if(year % 4 == 0){ 
    x -= /*leapeay seconds in february*/ 
}else{ 
    x -= /*regular seconds in february*/ 
} 
} 

//Then something like this: 

if(x > /*seconds in january*/){ 
x -= /*seconds in january*/ 
} 
if(x > /*seconds in february*/){ 
x -= /*seconds in january*/ 
} 

. 
. 
. 

//After that just get the number of days from x seconds and you're set. 

編輯

我建議使用最新功能簡單,但這裏是萬一有人可能不糊塗的備選答案需要它,還是會在意進一步發展它。

首先讓t爲從曆元開始的秒數。

設F是四年內的秒數。那是三年和一年閏年。那應該是:126230400.

現在如果你拿走F所貢獻的所有時間,你將得到一個餘數:y。

所以Y = N%F

有幾種情況現在: 1,y是不太有一年 2. y是不到兩年 3 y是不到三年的時間少兩個多月 4 y是不到三年的時間和更大的兩個多月 5 y是不到四年

注意,1972年是閏年,所以如果你從1970年,無論你計數四離開將是兩年的閏年。

讓jan,feb,febLY,mar,may,... dec分別爲每月的秒數(您需要計算出來)。

d代表當前月份的日期編號,D代表一天中的秒數(86400)。 y表示常規年份中的秒數,yLY表示閏年中的秒數。

y = (t % F) 
if(y < Y){ 
if(y > jan){ 
    y -= jan 
} 
if(y > feb){ 
    y -= feb 
} 
. 
. 
. 
d = y % D 
} 
else if(y < 2 * y){ 
y = y - Y 
if(y > jan){ 
    y -= jan 
} 
if(y > feb){ 
    y -= feb 
} 
. 
. 
. 
d = y % D 
} 
else if(y < 2 * y + yLY){ 
y = y - 2 * Y 
if(y > jan){ 
    y -= jan 
} 
if(y > febLY){ 
    y -= febLY 
} 
. 
. 
. 
d = y % D 
} 
else{ 
y = y - 2 * Y - yLY 
if(y > jan){ 
    y -= jan 
} 
if(y > feb){ 
    y -= feb 
} 
. 
. 
. 
d = y % D 
} 

未測試。另外,由於地球不會在1圈/ 24小時旋轉,所以偶爾會對時間進行調整。你需要做一些研究的因素是,在

+0

謝謝你,所以我認爲它能夠更好地計算它使用DATE函數,因爲我想把它放在sql查詢的中間。 –

+0

等一下,我明白了!請稍等,我會在上面發表我的回答。 – JSideris

2
t = unix time 
second = t MOD 60 
minute = INT(t/60) MOD 60 
hour = INT(t/60/60) MOD 24 
days = INT(t/60/60/24) 
years = INT(days/365.25) 
year = 1970 + years + 1 

1970年開始與週四的話,我們可以計算出星期幾。

weekday = (days + 4) MOD 7 

如果星期天是0天,如果您想要星期天是第1天,只需加1。

現在,讓我們來看看我們在這一年有多少天。

days = days - years * 365 - leapdays 

最後,我們找到月份的月份和日期。

IF year MOD 4 = 0 THEN ly = 1 ELSE ly = 0 
WHILE month <= 12 
    month = month + 1 
    IF month = 2 THEN 
     DaysInMonth = 28 + NOT(year MOD 4) + NOT(year MOD 100) 
      + NOT(year MOD 400) 
    ELSE 
     DaysInMonth = 30 + (month + (month < 7)) MOD 2 
    END IF 
    IF days > DaysInMonth THEN days = days - DaysInMonth 
END WHILE 

這是假設的TRUE = 1,FALSE = 0,不是真的= 0,沒有虛假記載,布爾值= 1

現在我們有一個月,小時的年,月,日,分鐘,第二次計算閏年調整。

3

A unix timestamp不包括leap seconds,所以我們不必擔心這一點。下面是一個分支少,用於從unix timestamp得到Y/M/d域環路少的算法:

#include <iostream> 

int 
main() 
{ 
    int s = 1313905026; 
    int z = s/86400 + 719468; 
    int era = (z >= 0 ? z : z - 146096)/146097; 
    unsigned doe = static_cast<unsigned>(z - era * 146097); 
    unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096)/365; 
    int y = static_cast<int>(yoe) + era * 400; 
    unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); 
    unsigned mp = (5*doy + 2)/153; 
    unsigned d = doy - (153*mp+2)/5 + 1; 
    unsigned m = mp + (mp < 10 ? 3 : -9); 
    y += (m <= 2); 
    std::cout << m << '/' << d << '/' << y << '\n'; // 8/21/2011 
} 

此輸出:

8/21/2011 

當你不感興趣在ym(只在d),你可以從上面的計算中消除最後幾行。

該算法在極其詳細的描述here中描述。鏈接包括一個完整的推導,以及跨越數百萬年的單元測試(這是過度殺傷)。


科少:是什麼樣子的算法小樹枝上面在-O3在MacOS優化掉的鏗鏘:

__Z14get_day_numberi:     ## @_Z14get_day_numberi 
    .cfi_startproc 
## BB#0: 
    pushq %rbp 
Ltmp0: 
    .cfi_def_cfa_offset 16 
Ltmp1: 
    .cfi_offset %rbp, -16 
    movq %rsp, %rbp 
Ltmp2: 
    .cfi_def_cfa_register %rbp 
    movslq %edi, %rax 
    imulq $-1037155065, %rax, %rcx ## imm = 0xFFFFFFFFC22E4507 
    shrq $32, %rcx 
    addl %ecx, %eax 
    movl %eax, %ecx 
    shrl $31, %ecx 
    sarl $16, %eax 
    leal (%rax,%rcx), %edx 
    leal 719468(%rax,%rcx), %esi 
    testl %esi, %esi 
    leal 573372(%rax,%rcx), %eax 
    cmovnsl %esi, %eax 
    cltq 
    imulq $963315389, %rax, %rcx ## imm = 0x396B06BD 
    movq %rcx, %rsi 
    shrq $63, %rsi 
    shrq $32, %rcx 
    sarl $15, %ecx 
    addl %esi, %ecx 
    imull $146097, %ecx, %ecx  ## imm = 0x23AB1 
    movl %eax, %esi 
    subl %ecx, %esi 
    subl %eax, %esi 
    leal 719468(%rsi,%rdx), %eax 
    movl %eax, %ecx 
    shrl $2, %ecx 
    imulq $1506180313, %rcx, %rdx ## imm = 0x59C67CD9 
    shrq $39, %rdx 
    movl %eax, %esi 
    subl %edx, %esi 
    imulq $963321983, %rcx, %rcx ## imm = 0x396B207F 
    shrq $43, %rcx 
    addl %esi, %ecx 
    movl %eax, %edx 
    shrl $4, %edx 
    imulq $7525953, %rdx, %rdx ## imm = 0x72D641 
    shrq $36, %rdx 
    subl %edx, %ecx 
    imulq $1729753953, %rcx, %rsi ## imm = 0x6719F361 
    shrq $32, %rsi 
    movl %ecx, %r8d 
    subl %ecx, %eax 
    movl %ecx, %edi 
    movl $3855821599, %edx  ## imm = 0xE5D32B1F 
    imulq %rcx, %rdx 
    subl %esi, %ecx 
    shrl %ecx 
    addl %esi, %ecx 
    shrl $8, %ecx 
    imull $365, %ecx, %ecx  ## imm = 0x16D 
    subl %ecx, %r8d 
    shrl $2, %edi 
    imulq $1506180313, %rdi, %rcx ## imm = 0x59C67CD9 
    shrq $39, %rcx 
    shrq $47, %rdx 
    addl %r8d, %eax 
    subl %ecx, %eax 
    leal (%rax,%rdx), %ecx 
    leal 2(%rcx,%rcx,4), %esi 
    movl $3593175255, %edi  ## imm = 0xD62B80D7 
    imulq %rsi, %rdi 
    shrq $39, %rdi 
    imull $153, %edi, %edi 
    subl %edi, %esi 
    leal 4(%rcx,%rcx,4), %ecx 
    subl %esi, %ecx 
    movl $3435973837, %esi  ## imm = 0xCCCCCCCD 
    imulq %rcx, %rsi 
    shrq $34, %rsi 
    leal 1(%rax,%rdx), %eax 
    subl %esi, %eax 
    popq %rbp 
    retq 
    .cfi_endproc 
+0

+1對於鏈接背後令人難以解釋的解釋:http://howardhinnant.github.io/date_algorithms.html#civil_from_days – Semo