Sind wir dann schon?

22

Ich bin ein Zeitreisender, und ich bin besessen vom Lauf der Zeit. Ich mag besonders die Momente, in denen die Uhrzeiger über 12 gehen, wenn ich auf die nächste Seite meines Kalenders blättern kann oder wenn alle "Frohes Neues Jahr!" Rufen.

Bitte schreiben Sie mir ein Programm, das mir in Form eines Fortschrittsbalkens anzeigt, wie weit ich vom letzten Moment bis zum nächsten bin. Wenn ich zum Beispiel sage, dass die Uhrzeit 09:12 Uhr ist, sollte Folgendes gedruckt werden:

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

Wenn ich sage, dass der Monat Mai 1982 ist, sollte dies gedruckt werden:

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

Habe ich erwähnt, dass ich Zeitreisender bin? Ich reise von der ersten Millisekunde von 0 n. Chr. Bis zur letzten Millisekunde von 9999 n. Chr. Überall hin, sodass das Programm jedes Datum und jede Uhrzeit in diesem Bereich verarbeiten muss.

Eingang

  • Die Eingabe erfolgt in einem der folgenden Formate:

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

    Dies sind die einzigen Formate, die verarbeitet werden müssen. Jeder Teil hat genau die angezeigte Anzahl von Ziffern, was bedeutet, dass Sekundenbruchteile nachgestellte Nullen haben können (z . B. .120nie .12). Dies Tist ein buchstäblicher Buchstabe "T", der das Datum von der Uhrzeit abgrenzt. Die Öffnungszeiten sind im 24-Stunden-Format.

  • Monate und Tage sind 1-basiert (mehr dazu weiter unten).

  • Ungültige und außerhalb des Bereichs liegende Eingaben müssen nicht verarbeitet werden.

  • Nach Ermessen des Programmierers kann die Eingabe eine einzige nachgestellte Zeile enthalten.

Fortschrittsbalken Mathe

Das Programm befasst sich mit den am wenigsten und zweitniedrigsten signifikanten Einheiten in der gegebenen Eingabe. Wenn die Eingabe beispielsweise tagesgenau ist 2016-12-14, zeigt der Fortschrittsbalken an, wie viel Prozent der Tage im Eingabemonat verstrichen sind und was noch übrig ist.

Der Fortschrittsbalken hat 20 Einheiten (Zeichen) und der dargestellte Anteil wird auf das nächste Inkrement von 120 gerundet . Angenommen 2016-12-14T12:28, der Fortschrittsbalken zeigt Runde ( 2860 × 20) = 9 von 20 Einheiten "gefüllt".

1-basierte Monate und Tage

Obwohl der Tag vom 1. Dezember (zum Beispiel) ist 01in 2016-12-01, für die Zwecke der Berechnung ist es der 0 - ten Tag des Monats, da die abgeschnittenen Einheiten mit der 0 - ten Millisekunde der 0 - ten Minute der 0 - ten Stunde des Tages bedeuten. Mit anderen Worten, 2016-12-01ist 031 des Weges bis Dezember und 2016-12-02ist 131 und so weiter.

Ebenso 2016-01ist die 0 - ten Millisekunde des 0 - ten Tag des Monats Januar, so in den Berechnungen ist es 0 / 12 , was bedeutet , 2016-12ist 11 / 12 .

Ja, das bedeutet, dass Monate und Tage den Fortschrittsbalken niemals vollständig ausfüllen.

Unterschiedliche Monatsdauern und Schaltjahre

Verschiedene Monate haben eine unterschiedliche Anzahl von Tagen, und die Ausgabe muss dies widerspiegeln - einschließlich Schaltjahren. Die Fortschrittsanzeige für den 6. Februar 2017 unterscheidet sich von der Fortschrittsanzeige für den 6. Februar 2016 (oder den 6. Januar beider Jahre).

Sonstiges

Ausgabe

Das Programm (oder die Funktion) muss einen horizontal ausgerichteten 20-stelligen Fortschrittsbalken drucken (oder als Zeichenfolge zurückgeben), der für die abgelaufene Zeit "ausgefüllt" und für die verbleibende Zeit "geöffnet" ist. Es muss von links nach rechts "ausfüllen".

Der Fortschrittsbalken muss links eine Beschriftung haben, die den Beginn der zu zählenden Periode anzeigt, und rechts eine Beschriftung, die den Beginn der nächsten Periode im gleichen Format wie die Eingabe anzeigt (jedoch nur zwei Genauigkeitseinheiten). Für unser Beispiel 2016-12-14wäre die gültige Ausgabe:

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

Hier sind die gültigen Etikettenformate für jeden der möglichen Zeiträume:

  • Monate: YYYY-MM
  • Tage: MM-DD
  • Std: DDThh
  • Protokoll: hh:mm
  • Sekunden: mm:ss
  • Millisekunden: ss.sss

Die Etiketten dürfen keine zusätzlichen Einheiten enthalten, und keine dürfen weggelassen werden.

Notizen ausgeben

  • Die "ausgefüllten" Einheiten des Fortschrittsbalkens werden durch ein #Zeichen dargestellt. "Offene" Einheiten werden durch dargestellt -.
  • Zwischen dem Fortschrittsbalken und jedem Etikett muss genau ein Leerzeichen sein.
  • Führende oder nachfolgende Leerzeichen und / oder eine einzelne nachfolgende Zeile sind zulässig.

Gewinnen

Das ist . Kürzester Code in Bytes gewinnt. Es gelten Standardregeln. Standardlücken verboten.

Beispiele

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
Jordan
quelle
4
Müssen wir uns um Schaltsekunden sorgen?
Riley
@ Riley Gute Frage. Nein
Jordan
2
Ich gehe davon aus, dass die Sommerzeit ignoriert wird, da es kein standardisiertes Formular gibt.
CAD97
3
@ CAD97 Gute Frage. Du hast Recht. Die Sommerzeit verkompliziert die Dinge für Zeitreisende wirklich, daher ignorieren wir sie.
Jordanien
Das Beispiel "1899-12-31T23" ist gemäß der angegebenen Liste der Eingabeformate nicht gültig. Dies gilt auch für "1982-05-15T17". Bitte überprüfen Sie Ihre Testdaten.
Zeppelin

Antworten:

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

Besteht alle Tests

(
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

Testfunktion druckt nichts für bestanden, Werte für nicht bestanden.

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

Die Testfälle:

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
quelle
2
Ich musste eine neue Sprache lernen, um diese Version zu verbessern ... sie ist sehr kurz!
Rexroni
3

Pyth, 213 Bytes

Mein erster Code in Pyth! Erblicken:

+%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

Mein Pyth-Code basiert stark auf meiner vorherigen Python-Antwort. Hier ist die ungolfed Version mit Kommentaren:

"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

Das Testen mehrerer Werte ist einfach, indem Sie die Codeschleife erstellen und am Ende einen Zeilenumbruch hinzufügen:

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"

Dann bin ich gelaufen cat testinput | pyth code.pyth > outputund diff output testoutput oder probiere es online aus .

rexroni
quelle
2

Python 2, 371 Bytes

Diese Herausforderung war überraschend schwierig! Es schien, als würde ich knapp unter 300 sein, bis ich die Formatierung der Ausgabezeichenfolge herausgefunden hatte.

Die Art von coolem Teil ist, dass meine Antwort kein Datumspaket verwendet:

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
quelle