Math 用数学方法从unix时间戳计算天数?
如何从unix时间戳以数学方式计算日数,而不使用任何函数和简单的数学公式Math 用数学方法从unix时间戳计算天数?,math,datetime,date,unix-timestamp,Math,Datetime,Date,Unix Timestamp,如何从unix时间戳以数学方式计算日数,而不使用任何函数和简单的数学公式 1313905026-->8(今天是2011年8月21日)没有简单的公式可以做到这一点。您需要减去自新纪元以来的年数(考虑闰年),这可能需要一个循环或某种离散计算。然后使用某种类型的循环减去当前年份每个月的秒数。剩下的是当月的秒数 我会这样做 x=…//秒数 年份=1970年 而(x>/*一年*/){ 1月和3月至12月的x=x-/*秒*/ 如果(第%4年==0){ 2月份的每秒钟x-=/*跳跃*/ }否则{ 二月的x-=
1313905026-->8(今天是2011年8月21日)没有简单的公式可以做到这一点。您需要减去自新纪元以来的年数(考虑闰年),这可能需要一个循环或某种离散计算。然后使用某种类型的循环减去当前年份每个月的秒数。剩下的是当月的秒数 我会这样做
x=…//秒数
年份=1970年
而(x>/*一年*/){
1月和3月至12月的x=x-/*秒*/
如果(第%4年==0){
2月份的每秒钟x-=/*跳跃*/
}否则{
二月的x-=/*常规秒数*/
}
}
//然后像这样:
如果(1月x>/*秒*/){
一月份的x-=/*秒*/
}
如果(2月x>/*秒*/){
一月份的x-=/*秒*/
}
.
.
.
//之后,只需从x秒开始计算天数,即可设置。
编辑
为了简单起见,我建议使用日期函数,但这里有一个可能的非循环替代答案,以防任何人需要它,或者希望进一步开发它
首先,t是自纪元以来的当前时间(以秒为单位)
设F为四年内的秒数。这是三个正常年份和一个闰年。这应该是:126230400
现在,如果你去掉F贡献的所有时间,你会得到一个余数:y
所以y=n%F
现在有几种情况:
1.y小于一年
2.y不到两年
3.y不到三年也不到两个月
4.y小于三年,大于两个月
5.y不到四年
请注意,1972年是闰年,所以如果你从1970年算起,再加上4年,无论你在哪里停下来,都将是两年后的闰年
让一月,二月,费布莱,三月,五月,…,十二月是每个月的秒数(你需要计算出来)
d表示当前月份的天数,d表示一天中的秒数(86400)。
y表示正常年份的秒数,yLY表示闰年的秒数
y=(t%F)
if(y1月){
y-=一月
}
如果(y>2月){
y-=feb
}
.
.
.
d=y%d
}
否则如果(y<2*y){
y=y-y
如果(y>1月){
y-=一月
}
如果(y>2月){
y-=feb
}
.
.
.
d=y%d
}
否则如果(y<2*y+yLY){
y=y-2*y
如果(y>1月){
y-=一月
}
如果(y>febLY){
y-=febLY
}
.
.
.
d=y%d
}
否则{
y=y-2*y-yLY
如果(y>1月){
y-=一月
}
如果(y>2月){
y-=feb
}
.
.
.
d=y%d
}
没有测试。此外,由于地球并不是以每24小时1圈的速度自转,他们偶尔会调整时间。你需要在这方面做一些研究
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
现在,让我们来看看我们进入这一年的天数
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
如果年份MOD 4=0,则ly=1,否则ly=0
而月份DaysInMonth则days=天-DaysInMonth
结束时
这假定布尔值为TRUE=1、FALSE=0、NOT TRUE=0和NOT FALSE=1
现在我们已经计算了年、月、月日、小时、分钟和秒,并对闰年进行了调整。A不包括在内,所以我们不必担心这一点。下面是一个无分支、无循环的算法,用于从a获取y/m/d字段:
由于您对y
和m
(仅在d
中)不感兴趣,因此可以从上述计算中删除最后几行
这个算法描述得非常详细。该链接包括一个完整的派生,以及跨越数百万年的单元测试(这太过分了)
1分支减少:在macOS上,通过在-O3上发出叮当声来优化上述算法中的小分支:
__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
锈迹斑斑:
fn date(mut months_to_shift: i32, timezone_shift: i32) -> String {
months_to_shift = months_to_shift * 2_628_000;
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Before time!")
.as_secs() as f32;
let adjusted_time = ((((timestamp / 31_557_600.0) / 4.0).round() as i32 * 86_400)
+ 604800
+ (timezone_shift * 3600)
+ months_to_shift) as f32
+ timestamp; // 608400 offset for number of days missing - 7 - (???) + leap year days +/- timezone shift from EST -- Using timezone shift in my project but not necessary
let years = (1970.0 + (adjusted_time / 31_536_000.0)) as i32;
let mut months = ((adjusted_time % 31_536_000.0) / 2_628_000.0) as i32;
months = if months == 0 { 12 } else { months };
let days = ((adjusted_time % 2_628_000.0) / 86_400.0) as i32;
years.to_string() + "-" + &months.to_string() + "-" + &days.to_string()
}
谢谢,所以我认为最好使用日期函数来计算它,因为我想把它放在sql查询的中间!请稍等,我将在上面发布我的答案。+1链接背后令人痛苦的解释:这个常数不是比
365.25
更多吗?
__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
fn date(mut months_to_shift: i32, timezone_shift: i32) -> String {
months_to_shift = months_to_shift * 2_628_000;
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Before time!")
.as_secs() as f32;
let adjusted_time = ((((timestamp / 31_557_600.0) / 4.0).round() as i32 * 86_400)
+ 604800
+ (timezone_shift * 3600)
+ months_to_shift) as f32
+ timestamp; // 608400 offset for number of days missing - 7 - (???) + leap year days +/- timezone shift from EST -- Using timezone shift in my project but not necessary
let years = (1970.0 + (adjusted_time / 31_536_000.0)) as i32;
let mut months = ((adjusted_time % 31_536_000.0) / 2_628_000.0) as i32;
months = if months == 0 { 12 } else { months };
let days = ((adjusted_time % 2_628_000.0) / 86_400.0) as i32;
years.to_string() + "-" + &months.to_string() + "-" + &days.to_string()
}