¿Estamos entonces todavía?

22

Soy un viajero del tiempo y estoy obsesionado con el paso del tiempo. En particular, me encantan los momentos en que las manecillas del reloj pasan las 12, o cuando puedo pasar a la siguiente página de mi calendario, o cuando todos gritan "¡Feliz Año Nuevo!"

Por favor, escriba para mí un programa que me muestre lo lejos que estoy desde el último momento hasta el siguiente, en forma de una barra de progreso. Por ejemplo, si le digo que son las 09:12, debería imprimir esto:

09:00 ####---------------- 10:00

Si le digo que el mes es mayo de 1982, debería imprimir esto:

1982-01 #######------------- 1983-01

¿Mencioné que soy un viajero en el tiempo? Viajo a cualquier lugar desde el primer milisegundo de 0 AD hasta el último milisegundo de 9999 AD, por lo que el programa necesita manejar cualquier fecha y hora en ese rango.

Entrada

  • La entrada estará en uno de los siguientes formatos:

    • YYYY-MM-DDThh:mm:ss.sss
    • YYYY-MM-DDThh:mm:ss
    • YYYY-MM-DDThh:mm
    • YYYY-MM-DDThh
    • YYYY-MM-DD
    • YYYY-MM

    Estos son los únicos formatos que deben manejarse. Cada parte tendrá exactamente el número de dígitos que se muestra, lo que significa que los segundos fraccionarios pueden tener ceros al final (por ejemplo .120, nunca .12). La Tes una letra literal "T" que delimita la fecha de la hora. Las horas son en un reloj de 24 horas.

  • Los meses y días están basados ​​en 1 (más sobre esto a continuación).

  • Las entradas inválidas y fuera de rango no necesitan ser manejadas.

  • A discreción del programador, la entrada puede tener una nueva línea final.

Barra de progreso matemática

El programa se refiere a las unidades menos y segunda menos significativas en la entrada dada. Por ejemplo, si la entrada tiene precisión a nivel de día (p 2016-12-14. Ej. ), La barra de progreso indicará qué proporción de los días en el mes de entrada han transcurrido frente a lo que queda.

La barra de progreso tendrá 20 unidades (caracteres) y la proporción representada se redondeará al incremento más cercano de 120 . Por ejemplo, dada 2016-12-14T12:28, la barra de progreso mostrará Ronda ( 2860 × 20) = 9 de 20 unidades "llenas".

1 meses y días

Aunque el día del 1 de diciembre (por ejemplo) está 01adentro 2016-12-01, para el cálculo es el día 0 del mes, porque las unidades truncadas implican el milésimo segundo del minuto 0 de la hora 0 del día. En otras palabras, 2016-12-01es 031 del camino hasta diciembre y 2016-12-02es 131 , y así sucesivamente.

Del mismo modo, 2016-01es el 0 milisegundo del día 0 de enero, por lo que en los cálculos es 012 , lo que significa que 2016-12es 1112 .

Sí, eso significa que meses y días nunca llenarán por completo la barra de progreso.

Diferentes duraciones de meses y años bisiestos

Diferentes meses tienen diferentes números de días y el resultado debe reflejar esto, incluidos los años bisiestos. La barra de progreso para el 6 de febrero de 2017 será diferente de la barra de progreso para el 6 de febrero de 2016 (o el 6 de enero de ambos años).

Diverso

  • Los viajeros en el tiempo utilizan el calendario gregoriano proleptico . TL; DR: No hay casos especiales como días perdidos en 1752 . La entrada incluirá fechas en el año 0 AD
  • Los viajeros del tiempo ignoran el horario de verano.
  • No se requiere que el programa tenga en cuenta los segundos bisiestos, pero puede hacerlo.

Salida

El programa (o función) debe imprimir (o devolver como una cadena) una barra de progreso de 20 caracteres orientada horizontalmente que se "rellena" durante el tiempo transcurrido y se "abre" durante el tiempo restante. Debe "completar" de izquierda a derecha.

La barra de progreso debe tener una etiqueta a su izquierda que muestre el comienzo del período que se cuenta y otra a la derecha que muestre el comienzo del siguiente período, en el mismo formato que la entrada (pero mostrando solo dos unidades de precisión). Para nuestro ejemplo, la 2016-12-14salida válida sería:

12-01 #########----------- 01-01

Estos son los formatos de etiqueta válidos para cada uno de los períodos posibles:

  • Meses: YYYY-MM
  • Dias: MM-DD
  • Horas: DDThh
  • Minutos: hh:mm
  • Segundos: mm:ss
  • Milisegundos: ss.sss

No se pueden incluir unidades adicionales en las etiquetas, y ninguna se puede omitir.

Notas de salida

  • Las unidades "rellenadas" de la barra de progreso estarán representadas por un #personaje. Las unidades "abiertas" estarán representadas por -.
  • Debe haber exactamente un espacio entre la barra de progreso y cada etiqueta.
  • Se permiten espacios iniciales o finales y / o una nueva línea final.

Victorioso

Este es el . El código más corto en bytes gana. Aplican reglas estándar. Lagunas estándar prohibidas.

Ejemplos

Input                      Output
-----------------------    -------------------------------------
2016-12-12T12:17           12:00 ######-------------- 13:00
2016-12-12                 12-01 #######------------- 01-01
0000-01-01T00:00:00.000    00.000 -------------------- 01.000
0000-01-01T00:00           00:00 -------------------- 01:00
1899-12-31T23              31T00 ###################- 01T00
1899-12-31                 12-01 ###################- 01-01
1899-12                    1899-01 ##################-- 1900-01
1982-05-15T17:15           17:00 #####--------------- 18:00
1982-05-15T17              15T00 ##############------ 16T00
1982-05                    1982-01 #######------------- 1983-01
9999-12-31T23:59:59.999    59.000 #################### 00.000
9999-12                    9999-01 ##################-- 10000-01
2000-01-06                 01-01 ###----------------- 02-01
2000-02-06                 02-01 ###----------------- 03-01
2001-02-06                 02-01 ####---------------- 03-01
1742-09-10                 09-01 ######-------------- 10-01
Jordán
fuente
44
¿Tenemos que preocuparnos por los segundos bisiestos?
Riley
@Riley Buena pregunta. No.
Jordania
2
Supongo que se ignora el horario de verano, ya que no hay un formulario estandarizado
CAD97
3
@ CAD97 Buena pregunta. Estás en lo correcto. El horario de verano realmente complica las cosas para los viajeros en el tiempo, por lo que lo ignoramos.
Jordania
El ejemplo "1899-12-31T23" no es válido de acuerdo con la lista de formatos de entrada proporcionada, lo mismo para "1982-05-15T17". Por favor verifique sus datos de prueba.
zeppelin

Respuestas:

4

JavaScript, 282 bytes

(x,v=x.split(/\D/g),l=v.length-2,[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),t=(v[l+1]-b)/d*20+.5|0,n=v[l],o=((n|0)+1)%a,r=l?('0'+o).slice(-2):o)=>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

Pasa todas las pruebas

(
x,
v=x.split(/\D/g),
l=v.length-2,
[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),
t=(v[l+1]-b)/d*20+.5|0,
n=v[l],
o=((n|0)+1)%a,
r=l?('0'+o).slice(-2):o
) =>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

La función de prueba no imprime nada para pasar, valores para fallar.

function test(value,expected){
    if (f(value)!=expected)
    {
        console.log(value);
        console.log(f(value));
        console.log(expected);
     }
}

Los casos de prueba:

test('2016-12-12T12:17','12:00 ######-------------- 13:00')                 ;
test('2016-12-12','12-01 #######------------- 01-01')                       ;
test('0000-01-01T00:00:00.000','00.000 -------------------- 01.000')        ;
test('0000-01-01T00:00','00:00 -------------------- 01:00')                 ;
test('1899-12-31T23','31T00 ###################- 01T00')                    ;
test('1899-12-31','12-01 ###################- 01-01')                       ;
test('1899-12','1899-01 ##################-- 1900-01')                      ;
test('1982-05-15T17:15','17:00 #####--------------- 18:00')                 ;
test('1982-05-15T17','15T00 ##############------ 16T00')                    ;
test('1982-05','1982-01 #######------------- 1983-01')                      ;
test('9999-12-31T23:59:59.999','59.000 #################### 00.000')        ;
test('9999-12','9999-01 ##################-- 10000-01')                     ;
test('2000-01-06','01-01 ###----------------- 02-01')                       ;
test('2000-02-06','02-01 ###----------------- 03-01')                       ;
test('2001-02-06','02-01 ####---------------- 03-01')                       ;
test('1742-09-10','09-01 ######-------------- 10-01')                       ;
Grax32
fuente
2
Tuve que aprender un nuevo idioma para encabezar esta versión ... ¡es muy conciso!
rexroni
3

Pyth, 213 bytes

Mi primer código en pyth! Mirad:

+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

Mi código pyth se basa estrechamente en mi respuesta anterior de python. Aquí está la versión sin golf con comentarios:

"K is the input, as a list of numbers"
Kr:w"[-T:.]"d7
"Y=year"
=YhK
"k=month"
=k@K1
"H = a list of denominators"
=H[0 ^9T 12 ?q2k+28+q0%Y4-q0%Y400q0%Y100 +30%+k/k8 2 24 60 60 999)
"J is the second-to-last number of the input"
J@K_2
"b is the +1 starting point for months and days"
=b<lK4
"G is the number of hashtags in the statusbar"
=Gs+*[email protected]
"N is the formatted string"
=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lK3 *2lK
+%hNJ+@N1+%eNb+d+*\#G+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

Probar múltiples valores se logra fácilmente haciendo el bucle de código y agregando una impresión de nueva línea al final:

Wp+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1+%eNb"\n"

Entonces me encontré cat testinput | pyth code.pyth > outputy diff output testoutput O intentarlo en línea .

rexroni
fuente
2

Python 2, 371 bytes

¡Este desafío fue sorprendentemente difícil! Parecía que iba a tener poco menos de 300 hasta que resolviera el formato de la cadena de salida.

El tipo de parte genial es que mi respuesta no usa ningún paquete de fecha:

import re
s=raw_input()
S=[int(i)for i in re.sub('[-T:.]',' ',s).split()]
l=len(S)
y,m=S[:2]
d=[0,20<<9,12,28+(y%4==0!=y%100)+(y%400==0)if m==2else 30+(m+m/8)%2,24,60,60,999]
a,n=S[-2:]
b=1-(1if l>3else 0)
h=int(20.*(n-b)/d[l]+.5)
x,y,z='- %.4d - %.2d - %.2d T %.2d : %.2d : %.2d . %.3d'.split()[l*2-3:l*2]
print x%a+y+z%b+' '+'#'*h+'-'*(20-h)+' '+x%((a+1)%d[l-1])+y+z%b
rexroni
fuente