2011-08-21 36 views

Trả lời

3

Không có công thức đơn giản để làm điều này. Bạn sẽ cần phải trừ số năm (tính cho năm nhuận) kể từ thời đại, mà có lẽ sẽ yêu cầu một vòng lặp hoặc một tính toán rời rạc của một số loại. Sau đó, sử dụng một số loại vòng lặp để trừ số giây trong mỗi tháng cho năm hiện tại. Những gì bạn còn lại là số giây hiện tại trong tháng.

Tôi sẽ làm một việc như thế này.

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. 

Sửa

tôi khuyên bạn nên sử dụng chức năng ngày vì đơn giản, nhưng đây là một câu trả lời thay thế phi điên rồ nhất có thể trong trường hợp bất cứ ai cần nó, hoặc sẽ quan tâm để phát triển nó hơn nữa.

Trước tiên hãy là thời gian hiện tại tính bằng giây kể từ thời đại.

Cho F là số giây trong bốn năm. Đó là ba năm thường xuyên và một năm nhuận. Đó là: 126230400.

Bây giờ nếu bạn lấy đi tất cả thời gian đóng góp của F, bạn sẽ nhận được phần còn lại: y.

Vì vậy, y = n% F.

Có một số trường hợp bây giờ: 1. y là ít mà một năm 2. y là chưa đầy hai năm 3. y là ít hơn ba năm và ít hơn hai tháng 4. y ít hơn ba năm và lớn hơn hai tháng 5. y là ít hơn bốn năm

Lưu ý rằng năm 1972 là năm nhuận, vì vậy nếu bạn đếm đến bốn từ năm 1970, bất cứ nơi nào bạn còn lại sẽ là một năm nhuận trong hai năm.

cho phép jan, feb, febLY, mar, may, ..., tháng mười hai là số giây trong mỗi tháng (bạn cần phải tính toán nó ra).

d đại diện cho số ngày của tháng hiện tại và D thể hiện số giây trong một ngày (86400). y đại diện cho số giây trong một năm thông thường và yLY biểu thị số giây trong một năm nhuận.

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 
} 

Không được kiểm tra. Ngoài ra, vì Trái Đất không quay ở vòng xoay CHÍNH XÁC 1/24 giờ, chúng thỉnh thoảng đã điều chỉnh theo thời gian. Bạn cần phải làm một chút yếu tố nghiên cứu rằng trong

+0

Cảm ơn bạn, vì vậy tôi nghĩ rằng nó tốt hơn để tính toán nó sử dụng các hàm DATE, vì tôi muốn đặt nó ở giữa truy vấn sql. –

+0

Đợi đã, tôi hiểu rồi! Chỉ cần đợi một chút và tôi sẽ đăng câu trả lời của tôi ở trên. – 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 bắt đầu với một ngày thứ năm như vậy, chúng ta có thể tính toán các ngày trong tuần:.

weekday = (days + 4) MOD 7 

Nếu Chúa nhật là ngày 0. Nếu bạn muốn chủ nhật là ngày 1 chỉ cần thêm 1.

Bây giờ, chúng ta hãy tìm hiểu xem chúng ta đang trải qua bao nhiêu ngày trong năm.

days = days - years * 365 - leapdays 

Cuối cùng, chúng tôi tìm thấy tháng và ngày trong tháng.

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 

này giả định giá trị Boolean của TRUE = 1, FALSE = 0, KHÔNG TRUE = 0, và NOT FALSE = 1.

Bây giờ chúng ta có năm, tháng, ngày tháng, giờ, phút và giây được tính toán với các điều chỉnh cho năm nhuận.

3

A unix timestamp không bao gồm leap seconds, vì vậy chúng tôi không phải lo lắng về điều đó. Đây là một ngành ít , thuật toán vòng lặp-less để nhận được y/m/d lĩnh vực từ một 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 
} 

đầu ra này:

8/21/2011 

Như bạn không quan tâm trong ym (chỉ trong số d), bạn có thể loại bỏ hai dòng cuối cùng khỏi tính toán ở trên.

Thuật toán này được mô tả chi tiết đầy đủ here. Liên kết bao gồm một dẫn xuất hoàn chỉnh và các bài kiểm tra đơn vị kéo dài hàng triệu năm (quá mức cần thiết).


Chi nhánh-less: Cái gì trông giống như các chi nhánh nhỏ trong thuật toán trên được tối ưu hóa đi kêu vang tại O3 trên hệ điều hành 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 cho các lời giải thích hấp dẫn đằng sau liên kết: http://howardhinnant.github.io/date_algorithms.html#civil_from_days – Semo

Các vấn đề liên quan