Conversión decimal de la hora del día

15

Introducción

El tiempo es confuso. Sesenta segundos a un minuto, sesenta minutos a una hora, veinticuatro horas a un día (¡sin mencionar esa molesta mañana / tarde!).

Hoy en día no hay lugar para tales tonterías, así que hemos decidido adoptar la única alternativa sensata: ¡días decimales! Es decir, cada día se considera 1 unidad completa, y cualquier cosa más corta se escribe como una fracción decimal de ese día. Entonces, por ejemplo: "12:00:00" se escribiría como "0.5" y "01:23:45" podría escribirse como "0.058159".

Debido a que llevará tiempo acostumbrarse al nuevo sistema, tiene la tarea de escribir un programa que pueda convertir entre ellos en ambas direcciones.

Desafío

Escriba un programa en el idioma que elija, que dado un tiempo moderno en el formato ISO-8601 de "hh: mm: ss", devolverá la unidad de fracción decimal equivalente. Asimismo, dada una fracción decimal, el programa debería devolver la hora en el formato moderno inicialmente especificado.

Puede hacer los siguientes supuestos:

  • La entrada y salida de tiempo moderno puede variar de "00:00:00" a "24:00:00"
  • La entrada y salida de tiempo decimal puede variar de "0" a "1", y debe ser capaz de aceptar / emitir hasta al menos 5 decimales (como "0.12345"). Más precisión es aceptable
  • El programa debería poder saber qué dirección de conversión realizar en función de la entrada
  • No puede usar funciones / bibliotecas relacionadas con el tiempo

El ganador será determinado por el código más corto que cumpla con los criterios. Se seleccionarán en al menos 7 unidades de día decimal, o si / cuando ha habido suficientes envíos.

Ejemplos

Aquí hay una (n intencionalmente) pieza de código JavaScript mal escrita para usar como ejemplo:

function decimalDay(hms) {
    var x, h, m, s;
    if (typeof hms === 'string' && hms.indexOf(':') > -1) {
        x = hms.split(':');
        return (x[0] * 3600 + x[1] * 60 + x[2] * 1) / 86400;
    }
    h = Math.floor(hms * 24) % 24;
    m = Math.floor(hms * 1440) % 60;
    s = Math.floor(hms * 86400) % 60;
    return (h > 9 ? '' : '0') + h + ':' + (m > 9 ? '' : '0') + m + ':' + (s > 9 ? '' : '0') + s;
}
decimalDay('02:57:46'); // 0.12344907407407407
decimalDay('23:42:12'); // 0.9876388888888888
decimalDay(0.5); // 12:00:00
decimalDay(0.05816); // 01:23:45
Mwr247
fuente
Hmm ... 60 es casi 64. Me pregunto cómo sería el tiempo si hubiera 64 segundos en un minuto y 64 minutos en una hora (y 16 o 32 horas en un día).
1
¿Tenemos que manejar los segundos bisiestos? Entonces, ¿23:59:60 es 1 segundo desde el final de un segundo día 86401?
Sparr
1
@Sparr No necesita preocuparse por los segundos intercalares. Este es el futuro, donde hemos decidido que es tonto por un segundo ser considerado un valor absoluto, al mismo tiempo que lo relacionamos con la velocidad relativa de la rotación de la tierra;)
Mwr247
1
@MichaelT Sería un mundo de sueños para programadores = P
Mwr247
1
@ Mwr247 sí. DNS TTL tiene (¿tenía?) Un campo que es ndonde nestá 2 ^ n segundos. Entonces, un valor de '6' tenía un TTL de aproximadamente 1 minuto. Un valor de '12' tenía un TTL de aproximadamente 1 hora. '15' fue alrededor de 8 horas y así sucesivamente. Permitió que un byte definiera el tiempo de espera y le diera suficiente control por períodos cortos o largos.

Respuestas:

6

CJam, 58 56 42 bytes

Estoy seguro de que esto es demasiado largo y se puede jugar mucho al golf. Pero aquí va para empezar:

86400q':/:d_,({60bd\/}{~*i60b{s2Ue[}%':*}?

Pruébalo en línea aquí

Optimizador
fuente
Je, tenemos ideas similares
aditsu
@aditsu ¡Oh! No vi el tuyo antes de actualizar el mío y luego tuve prisa por viajar.
Optimizador
Sabes qué ... no dudes en usar mi código: 86400q':/:d_,({60bd\/}{~*mo60bAfmd2/':*}?estoy borrando mi respuesta. El moes para que 0.058159 se convierta a 01:23:45
aditsu
3

Python 2, 159 150 141 + 2 = 143 Bytes

Solución directa, probablemente puede ser mucho más corta. Trabajaré en ello.

Se agregaron dos bytes para tener en cuenta la entrada que debe incluirse en "s". Además, Sp3000 señaló un problema con la evaluación de los octales de evaluación (), y mostró una forma de acortar el formato, usar map () y eliminar una impresión.

n=input();i=float;d=864e2
if':'in n:a,b,c=map(i,n.split(':'));o=a/24+b/1440+c/d
else:n=i(n);o=(':%02d'*3%(n*24,n*1440%60,n*d%60))[1:]
print o

Échale un vistazo a ideone aquí.

Kade
fuente
2

Javascript ( ES6 ), 116 110 bytes

f=x=>x[0]?([h,m,s]=x.split(':'),+s+m*60+h*3600)/86400:[24,60,60].map(y=>('0'+~~(x*=y)%60).slice(-2)).join(':')


// for snippet demo:
i=prompt();
i=i==+i?+i:i; // convert decimal string to number type
alert(f(i))

Comentado:

f=x=>
    x[0] ? // if x is a string (has a defined property at '0')
        ([h, m, s] = x.split(':'), // split into hours, minutes, seconds
        +s + m*60 + h*3600) // calculate number of seconds
        / 86400 // divide by seconds in a day
    : // else
        [24, 60, 60]. // array of hours, minutes, seconds
        map(y=> // map each with function
            ('0' + // prepend with string zero
                ~~(x *= y) // multiply x by y and floor it
                % 60 // get remainder
            ).slice(-2) // get last 2 digits
        ).join(':') // join resulting array with colons
nderscore
fuente
24:00:00produce 1pero lo inverso no es cierto
rink.attendant.6
@ rink.attendant.6 fijo
nderscore
2

Python 3: 143 bytes

i,k,l,m=input(),60,86400,float
if'.'in i:i=m(i)*l;m=(3*':%02d'%(i/k/k,i/k%k,i%k))[1:]
else:a,b,c=map(m,i.split(':'));m=(a*k*k+b*k+c)/l
print(m)

El mismo número de bytes que la solución de Python 2, pero parece que tomamos diferentes enfoques para las matemáticas.

Serdalis
fuente
2

Julia, 152 143 142 bytes

Bueno, actualicé mi enfoque para ser menos "juliano", como dicen, por el bien del golf. Para un enfoque mejor (aunque menos conciso), consulte el historial de revisiones.

x->(t=[3600,60,1];d=86400;typeof(x)<:String?dot(int(split(x,":")),t)/d:(x*=d;o="";for i=t q,x=x÷i,x%i;o*=lpad(int(q),2,0)*":"end;o[1:end-1]))

Esto crea una función sin nombre que acepta una cadena o un número de coma flotante de 64 bits y devuelve un número o cadena de coma flotante de 64 bits, respectivamente. Para llamarlo, asígnele un nombre, por ejemplo f=x->....

Ungolfed + explicación:

function f(x)
    # Construct a vector of the number of seconds in an hour,
    # minute, and second
    t = [3600, 60, 1]

    # Store the number of seconds in 24 hours
    d = 86400

    # Does the type of x inherit from the type String?
    if typeof(x) <: String
        # Compute the total number of observed seconds as the
        # dot product of the time split into a vector with the
        # number of seconds in an hour, minute, and second
        s = dot(int(split(x, ":")), t)

        # Get the proportion of the day by dividing this by
        # the number of seconds in 24 hours
        s / d
    else
        # Convert x to the number of observed seconds
        x *= d

        # Initialize an output string
        o = ""

        # Loop over the number of seconds in each time unit
        for i in t
            # Set q to be the quotient and x to be the remainder
            # from x divided by i
            q, x = divrem(x, i)

            # Append q to o, padded with zeroes as necessary
            o *= lpad(int(q), 2, 0) * ":"
        end

        # o has a trailing :, so return everything up to that
        o[1:end-1]
    end
end

Ejemplos:

julia> f("23:42:12")
0.9876388888888888

julia> f(0.9876388888888888)
"23:42:12"

julia> f(f("23:42:12"))
"23:42:12"
Alex A.
fuente
2

C, 137 bytes

Programa completo C. Toma entrada en stdin y salidas en stdout.

main(c){float a,b;scanf("%f:%f:%d",&a,&b,&c)<3?c=a*86400,printf("%02d:%02d:%02d",c/3600,c/60%60,c%60):printf("%f",a/24+b/1440+c/86400.);}

Ungolfed y comentó:

int main() {
    // b is float to save a . on 1440
    float a,b;
    // c is int to implicitly cast floats
    int c;

    // If the input is hh:mm:ss it gets splitted into a, b, c
    // Three arguments are filled, so ret = 3
    // If the input is a float, it gets stored in a
    // scanf stops at the first semicolon and only fills a, so ret = 1
    int ret = scanf("%f:%f:%d", &a, &b, &c);

    if(ret < 3) {
        // Got a float, convert to time
        // c = number of seconds from 00:00:00
        c = a * 86400;
        printf("%02d:%02d:%02d", c/3600, c/60 % 60, c%60);
    }
    else {
        // a = hh, b = mm, c = ss
        // In one day there are:
        // 24 hours
        // 1440 minutes
        // 86400 seconds
        printf("%f", a/24 + b/1440 + c/86400.);
    }
}
Andrea Biondo
fuente
Uso muy claro de scanf y% f
algún usuario
D'oh! Quise decir "inteligente".
algún usuario
2

J, 85 bytes

Resultados:

T '12: 00: 00 '
0.5

T 0.5
12 0 0

T '12: 34: 56 '
0.524259

T 0.524259
12 34 56

T=:3 :'a=.86400 if.1=#y do.>.(24 60 60#:y*a)else.a%~+/3600 60 1*".y#~#:192 24 3 end.'

Total 85

Richard Donovan
fuente
Bienvenido al sitio! Edité tu publicación para que el código se muestre como código. En cuanto a un enlace en línea, el mejor que conozco es TIO . Te daría un enlace, pero no tengo experiencia con J, así que no sé la forma correcta de invocarlo. Además, esto parece ser 91 bytes cuando incluye la primera y la última línea. ¿Es esto correcto?
DJMcMayhem
¡Gracias por tu ayuda! El programa [a = ... hasta el final.] Es 77. El título es 10. El terminador es 1, entonces eso hace 88. ¡Con tres avances de línea que hacen 91! Trabajaré en ello: o)
Richard Donovan
¡Ahora a un byte de 85 bytes!
Richard Donovan
1

Javascript, 194 192 190 188 bytes

function(z){if(isNaN(z)){x=z.split(':');return x[0]/24+x[1]/1440+x[2]/86400}h=(z*24)|0;h%=24;m=(z*1440)|0;m%=60;s=(z*86400)|0;s%=60;return""+(h>9?'':0)+h+':'+(m>9?'':0)+m+':'+(s>9?'':0)+s}
SuperJedi224
fuente
1

JavaScript ES6, 98 130 bytes

s=>s==+s?'246060'.replace(/../g,l=>':'+('0'+~~(s*=+l)%60).slice(-2)).slice(1):s.split`:`.reduce((a,b)=>+b+(+a)*60)*1/864e2;f(0.5);
Downgoat
fuente
Desafortunadamente, las funciones relacionadas con el tiempo (como "Fecha" y "toTimeString") no están permitidas en este desafío. De lo contrario, es una forma mucho más concisa de hacerlo =)
Mwr247
@ Mwr247 oh, no vi eso, arreglaré esto entonces
Downgoat
1

C, 156 152 bytes

Pensé que iba a ser fácil para C. Pero aún así terminó siendo bastante grande. :(

n,m=60;d(char*s){strchr(s,58)?printf("%f",(float)(atoi(s)*m*m+atoi(s+3)*m+atoi(s+6))/m/m/24):printf("%02d:%02d:%02d",(n=atof(s)*m*m*24)/m/m,n/m%m,n%m);}

Programa de prueba:

#include <stdio.h>
#include <stdlib.h>

int n,m=60;
d(char*s)
{
    strchr(s,':') ? 
        printf("%f",(float)(atoi(s)*m*m+atoi(s+3)*m+atoi(s+6))/m/m/24):
        printf("%02d:%02d:%02d",(n=atof(s)*m*m*24)/m/m,n/m%m,n%m);
}

int main()
{
    d("01:23:45");
    printf("\n");
    d("02:57:46");
    printf("\n");
    d("23:42:12");
    printf("\n");
    d("12:00:00");
    printf("\n");
    d("0.5");
    printf("\n");
    d("0.05816");
    printf("\n");
    d("0");
    printf("\n");
    d("1");
    printf("\n");
    return 0;
}

Salida:

0.058160
0.123449
0.987639
0.500000
12:00:00
01:23:45
00:00:00
24:00:00
algun usuario
fuente
1

PHP, 70 69 bytes

<?=strpos($t=$argv[1],58)?strtotime($t)/86400:date("H:i:s",$t*86400);

toma la entrada del argumento de la línea de comando, imprime en STDOUT:

Si la entrada contiene dos puntos, conviértala en tiempo de Unix y divídala entre (segundos por día); de lo
contrario , multiplique el valor numérico con (segundos por día) y formatee el tiempo de Unix en hh:mm:ss.

Titus
fuente
1

Perl, 109 108 101 + 6 ( -plaF:flag) = 107 bytes

$_=$#F?($F[0]*60+$F[1]+$F[2]/60)/1440:sprintf"%02d:%02d:%02d",$h=$_*24,$m=($h-int$h)*60,($m-int$m)*60

Utilizando:

perl -plaF: -e '$_=$#F?($F[0]*60+$F[1]+$F[2]/60)/1440:sprintf"%02d:%02d:%02d",$h=$_*24,$m=($h-int$h)*60,($m-int$m)*60' <<< 01:23:45

Pruébalo en Ideone.

Denis Ibaev
fuente
0

Excel, 178 bytes

=IF(LEFT(A1,2)="0.",TEXT(FLOOR(A1*24,1),"00")&":"&TEXT(MOD(FLOOR(A1*1440,1),60),"00")&":"&TEXT(MOD(FLOOR(A1*86400,1),60),"00"),((LEFT(A1,2)*60+MID(A1,4,2))*60+RIGHT(A1,2))/86400)
Wernisch
fuente