Làm cách nào để tôi có thể tính số ngày từ một dấu thời gian, theo cách toán học và không sử dụng bất kỳ hàm nào và trong công thức toán đơn giản.Tính số ngày từ một dấu thời gian trong một cách toán học?
1313905026 -> 8 (Hôm nay 2011/08/21)
Làm cách nào để tôi có thể tính số ngày từ một dấu thời gian, theo cách toán học và không sử dụng bất kỳ hàm nào và trong công thức toán đơn giản.Tính số ngày từ một dấu thời gian trong một cách toán học?
1313905026 -> 8 (Hôm nay 2011/08/21)
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
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.
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 y
và m
(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
+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ả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. –
Đợ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