2011-08-21 13 views

Respuesta

3

no existe una fórmula simple de hacer esto. Debería restar el número de años (contabilizando los años bisiestos) desde la época, lo que probablemente requeriría un ciclo o un cálculo discreto de algún tipo. Luego use algún tipo de ciclo para restar el número de segundos en cada mes para el año actual. Lo que le queda es la cantidad de segundos actualmente en el mes.

Haría algo como esto.

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. 

Edición

recomiendo el uso de las funciones de fecha para la simplicidad, pero aquí hay una posible respuesta alternativa no descabellada por si alguien lo necesita, o le importaría a desarrollarla.

Primero, sea el tiempo actual en segundos desde la época.

Sea F la cantidad de segundos en cuatro años. Eso es tres años regulares y un año bisiesto. Eso debería ser: 126230400.

Ahora, si quita todo el tiempo contribuido por F, obtendrá un resto: y.

Así y = n% F.

Hay varios casos ahora: 1. y es menos de un año 2. y es menor de dos años 3. Y es menos de tres años y menos de dos meses 4. y es menos de tres años y mayores de dos meses 5. y es inferior a cuatro años

Tenga en cuenta que 1972 fue un año bisiesto, por lo que si se cuentan por cuatro desde 1970, donde quiera que quedaría apagado será un año bisiesto en dos años.

deje enero, febrero, febrero, mayo, ..., dec la cantidad de segundos en cada mes (debe calcularla).

d representa el número del día del mes actual y D representa la cantidad de segundos en un día (86400). y representa el número de segundos en un año regular, y yLY representa el número de segundos en un año bisiesto.

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 
} 

no ensayado. Además, dado que la Tierra no gira EXACTAMENTE 1 rotación/24 horas, ocasionalmente han hecho ajustes en el tiempo. Es necesario hacer un poco de factor de investigación que en

+0

Gracias, por lo que creo que es mejor calcular usando las funciones DATE porque quiero ubicarlo en medio de una consulta SQL. –

+0

¡Espera, lo tengo! Espera un segundo y publicaré mi respuesta más arriba. – 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 comenzó con un jueves así, podemos calcular el día de la semana:.

weekday = (days + 4) MOD 7 

Si el domingo es el día 0. Si quiero que el domingo sea el día 1 solo agregue 1.

Ahora, descubramos cuántos días estamos en el año en cuestión.

days = days - years * 365 - leapdays 

Finalmente, encontramos el mes y el día del mes.

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 

Esto asume valores booleanos de TRUE = 1, 0 = FALSO, NO ES VERDAD = 0, y = FALSO NO 1.

Ahora tenemos el año, mes, día del mes, hora, minuto y segundo calculado con ajustes para años bisiestos.

3

A unix timestamp no incluye leap seconds, por lo que no tenemos que preocuparnos por eso. Aquí es una rama menos -1, el algoritmo de bucle menor para conseguir los A/M/D campos de un 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 
} 

Este salidas:

8/21/2011 

Como usted no está interesado en y y m (solo en d), puede eliminar las últimas dos líneas del cómputo anterior.

Este algoritmo se describe en detalle insoportable here. El enlace incluye una derivación completa y pruebas unitarias que abarcan millones de años (lo cual es excesivo).


Rama-menos: Lo que parece pequeñas sucursales en el algoritmo anterior se han optimizado de distancia por sonido metálico en -O3 en 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 por las insoportables explicaciones detrás del enlace: http://howardhinnant.github.io/date_algorithms.html#civil_from_days – Semo

Cuestiones relacionadas