2011-08-21 8 views

Odpowiedz

3

Nie ma prostej formuły, aby to zrobić. Będziesz musiał odjąć liczbę lat (licząc lata przestępne) od epoki, która prawdopodobnie wymagałaby pętli lub dyskretnych obliczeń. Następnie użyj pewnego rodzaju pętli, aby odjąć liczbę sekund w każdym miesiącu dla bieżącego roku. Pozostaje ci liczba sekund aktualnie w miesiącu.

Chciałbym zrobić coś takiego.

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. 

Edit

Polecam przy użyciu funkcji date dla uproszczenia, ale tutaj jest to możliwe bez loopy odpowiedź alternatywą na wypadek gdyby ktoś go potrzebuje, czy też obchodzi go dalej rozwijać.

Pierwsza litera t to aktualny czas w sekundach od epoki.

Niech F będzie liczbą sekund w ciągu czterech lat. To trzy lata regularne i jeden rok przestępny. To powinno być: 126230400.

Teraz, jeśli zabierzecie cały czas wnoszony przez F, otrzymacie resztę: y.

więc y = n% F.

Istnieje kilka przypadków teraz: 1. y jest mniejsza, że ​​rok 2. y jest krótszy niż dwa lata 3. Y jest mniej niż trzy lata i mniej niż dwa miesiące 4. y jest mniejsza niż trzy lata i dłuższy niż dwa miesiące 5. y wynosi mniej niż cztery lata

Należy pamiętać, że 1972 był rokiem przestępnym, więc jeśli liczyć się czterokrotnie od 1970 roku, gdziekolwiek przerwany będzie rokiem przestępnym za dwa lata.

niech jan, feb, febLY, mar, may, ..., dec będzie liczbą sekund w każdym miesiącu (trzeba to obliczyć).

d oznacza numer dnia bieżącego miesiąca, a D oznacza liczbę sekund w ciągu dnia (86400). y oznacza liczbę sekund w zwykłym roku, a yLY oznacza liczbę sekund w roku przestępnym.

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 
} 

nie testowano. Ponadto, ponieważ Ziemia nie wiruje z DOKŁADNIE 1 obrotu/24 godziny, od czasu do czasu dokonywała korekty czasu. Trzeba zrobić trochę badań czynnik, który w

+0

Dziękuję, więc myślę, że lepiej, aby obliczyć używają funkcji DATE, ponieważ chcę umieścić go w środku kwerendy sql. –

+0

Czekaj, mam! Po prostu powiesić na sekundę, a ja zamieszczę moją odpowiedź powyżej. – 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 rozpoczął się w czwartek, więc możemy obliczyć dzień tygodnia.

weekday = (days + 4) MOD 7 

Jeśli Niedziela to dzień 0. Jeśli chcesz niedziela być dniem 1 po prostu dodaj 1.

Zobaczmy teraz, ile dni jesteśmy w danym roku.

days = days - years * 365 - leapdays 

Wreszcie znajdujemy miesiąc i dzień miesiąca.

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 

Zakłada Boolean wartości PRAWDA = 1, FALSE = 0, nie jest prawdą = 0, a NIE FAŁSZ = 1.

Teraz mamy rok, miesiąc, dzień miesiąca, godzinę, minuta, a druga obliczona z korektami w latach przestępnych.

3

A unix timestamp nie obejmuje leap seconds, więc nie musimy się o to martwić. Oto oddział mniej algorytm pętli mniej za coraz Y/M/d pola z unix timestamp:

#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 
} 

This wyjścia:

8/21/2011 

jak nie jesteś zainteresowany w y i m (tylko w d) można wyeliminować ostatnie kilka linii z powyższego obliczenia.

Algorytm ten opisany jest w rozdzierających szczegółach: here. Łącze zawiera pełne wyprowadzenie i testy jednostkowe obejmujące miliony lat (co jest przesadą).


Oddział mniej: Co wygląda małych oddziałów w algorytmie powyżej są zoptymalizowane z dala od brzękiem na -O3 na 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 za rozdzierające wyjaśnienia dotyczące linku: http://howardhinnant.github.io/date_algorithms.html#civil_from_days – Semo

Powiązane problemy