Conversão da hora decimal do dia

15

Introdução

O tempo é confuso. Sessenta segundos a um minuto, sessenta minutos a uma hora, vinte e quatro horas por dia (e para não mencionar essa manhã am / pm!).

Atualmente, não há espaço para essa tolice, por isso decidimos adotar a única alternativa sensata: dias decimais! Ou seja, cada dia é considerado 1 unidade inteira e qualquer coisa mais curta é escrita como uma fração decimal desse dia. Assim, por exemplo: "12:00:00" seria escrito como "0,5" e "01:23:45" poderia ser escrito como "0,058159".

Como levará tempo para se acostumar com o novo sistema, você terá a tarefa de escrever um programa que possa ser convertido entre eles nas duas direções.

Desafio

Escreva um programa no idioma de sua escolha que, dado um tempo moderno no formato ISO-8601 de "hh: mm: ss", retorne a unidade de fração decimal equivalente. Da mesma forma, dada uma fração decimal, o programa deve retornar o tempo no formato moderno especificado inicialmente.

Você pode fazer as seguintes suposições:

  • A entrada e saída de tempo modernos podem variar de "00:00:00" a "24:00:00"
  • A entrada e saída de tempo decimal podem variar de "0" a "1" e devem poder aceitar / produzir até pelo menos 5 casas decimais (como "0,12345"). Mais precisão é aceitável
  • O programa deve saber qual direção de conversão executar com base na entrada
  • Você não pode usar funções / bibliotecas relacionadas ao tempo

O vencedor será determinado pelo código mais curto que atender aos critérios. Eles serão selecionados em pelo menos 7 unidades de dia decimal, ou se / quando houver envios suficientes.

Exemplos

Aqui está um (n intencionalmente) trecho de código JavaScript mal escrito para ser usado como exemplo:

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
fonte
Hmm ... 60 é quase 64. Gostaria de saber que horas seriam se houvesse 64 segundos em um minuto e 64 minutos em uma hora (e 16 ou 32 horas em um dia).
1
Temos que lidar com segundos bissextos? então 23:59:60 é de 1 segundo após o final de um segundo dia de 86401?
Sparr
1
@Sparr Não precisa se preocupar com segundos bissextos. Este é o futuro, onde decidimos que é bobagem para um segundo para ser considerado um valor absoluto ao mesmo tempo, amarrando-o com a velocidade relativa da rotação da Terra;)
Mwr247
1
@MichaelT Seria uma programadores sonhar mundo = P
Mwr247
1
@ Mwr247 sim. DNS TTL tem (ainda?) Um campo que é nonde nestá a 2 ^ n segundos. Portanto, um valor de '6' tinha um TTL de cerca de 1 minuto. Um valor de '12' tinha um TTL de cerca de 1 hora. '15' durou cerca de 8 horas e assim por diante. Ele permitiu que um byte definisse o tempo limite e lhe desse controle suficiente por períodos curtos ou longos.

Respostas:

6

CJam, 58 56 42 bytes

Tenho certeza que isso é muito longo e pode ser jogado muito. Mas aqui vai para iniciantes:

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

Experimente online aqui

Optimizer
fonte
Heh, temos ideias semelhantes
aditsu
@aditsu Oh !. Não viu o seu antes de atualizar o meu e, em seguida, estava com pressa de comutar.
Optimizer
Você sabe o que .. sinta-se à vontade para usar meu código 86400q':/:d_,({60bd\/}{~*mo60bAfmd2/':*}?:, estou excluindo minha resposta. A moé para que 0.058159 convertidos para 01:23:45
aditsu
3

Python 2, 159 150 141 + 2 = 143 bytes

Solução simples, provavelmente pode ser muito mais curta. Vai trabalhar nisso.

Foram adicionados dois bytes para considerar a entrada que precisa ser incluída em "s. Além disso, o Sp3000 apontou um problema com a interpretação de octais de eval () e mostrou uma maneira de reduzir a formatação, usar map () e remover uma impressão.

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

Confira em ideone aqui.

Kade
fonte
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
fonte
24:00:00O resultado é 1o inverso, mas o inverso não é verdadeiro
rink.attendant
@ rink.attendant.6 fixed
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)

Contagem de mesmos bytes que a solução python 2, mas parece que adotamos abordagens diferentes para a matemática.

Serdalis
fonte
2

Julia, 152 143 142 bytes

Bem, atualizei minha abordagem para ser menos "juliana", como se costuma dizer, em prol do golfe. Para uma abordagem melhor (embora menos concisa), consulte o histórico de revisões.

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]))

Isso cria uma função sem nome que aceita uma sequência de caracteres ou um número de ponto flutuante de 64 bits e retorna um número ou sequência de ponto flutuante de 64 bits, respectivamente. Para chamá-lo, dê um nome, por exemplof=x->... .

Ungolfed + explicação:

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

Exemplos:

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.
fonte
2

C, 137 bytes

Programa C completo. Aceita stdin e produz 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 e comentou:

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
fonte
Uso muito claro de scanf e% f
algum usuário
D'oh! Eu quis dizer "inteligente".
algum usuário
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
fonte
Bem vindo ao site! Editei sua postagem para que o código seja exibido como código. Quanto a um link on-line, o melhor que eu conheço é o TIO . Eu daria a você um link, mas não tenho experiência com J, então não sei o caminho certo para invocá-lo. Além disso, isso parece ter 91 bytes quando você inclui a primeira e a última linhas. Isso está correto?
DJMcMayhem
Obrigado pela ajuda! O programa [a = ... até o final.] É 77. O título é 10. O terminador é 1, o que significa 88. Com três feeds de linha, o número 91! Vou trabalhar nisso: o)
Richard Donovan
Agora, com apenas uma linha 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
fonte
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
fonte
Infelizmente, funções relacionadas ao horário (como "Data" e "toTimeString") não são permitidas neste desafio. Caso contrário, é uma forma muito mais concisa de fazê-lo =)
Mwr247
@ Mwr247 oh não vi isso, eu vou ser a fixação deste então
Downgoat
1

C, 156 152 bytes

Eu pensei que seria fácil para C. Mas ainda acabou bem 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 teste:

#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;
}

Resultado:

0.058160
0.123449
0.987639
0.500000
12:00:00
01:23:45
00:00:00
24:00:00
algum usuário
fonte
1

PHP, 70 69 bytes

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

recebe entrada do argumento da linha de comando, imprime em STDOUT:

Se a entrada contiver dois pontos, converta para hora unix e divida por (segundos por dia), caso
contrário , multiplique o valor numérico por (segundos por dia) e formate a hora unix para hh:mm:ss.

Titus
fonte
1

Perl, 109 108 101 + 6 ( -plaF:sinalizador) = 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

Usando:

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

Experimente em Ideone.

Denis Ibaev
fonte
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
fonte