Konvertieren Sie einen Excel-Datumscode in ein "Datum"


15

Bei einem nicht negativen ganzzahligen Datumscode im Excel-Stil geben Sie das entsprechende "Datum" in einer angemessenen Form zurück, in der Jahr, Monat und "Tag" deutlich angegeben sind.

Trivial, könnte man meinen. Haben Sie die "Angstzitate" bemerkt? Ich habe diese verwendet, weil Excel einige Macken hat. Excel zählt Tage mit der Nummer 1 für den Monat Januar 1 st , 1900, aber als ob 1900 einen Januar hatte 0 - ten und 29. Februar th , so sehr vorsichtig sein , alle Testfälle , um zu versuchen:

 Input → Output (example format)
     0 → 1900-01-00    Note: NOT 1899-12-31
     1 → 1900-01-01
     2 → 1900-01-02
    59 → 1900-02-28
    60 → 1900-02-29    Note: NOT 1900-03-01
    61 → 1900-03-01
   100 → 1900-04-09
  1000 → 1902-09-26
 10000 → 1927-05-18
100000 → 2173-10-14

1
Hat jedes Jahr einen 0. Januar und 29. Februar oder ist 1900 die einzige Anomalie?
Shaggy

4
1900 ist die Anomalie. Excel behandelt Schaltjahre korrekt mit Ausnahme von 1900 (das kein Schaltjahr ist). Aber das war aus Kompatibilitätsgründen mit Lotus 1-2-3, wo der Fehler entstand.
Rick Hitchcock

3
@ RickHitchcock Anscheinend haben die Lotus 1-2-3-Entwickler alles getan, um Schaltjahr-Code zu sparen, sodass die Regel einfach alle vier Jahre gilt. Mit gutem Grund auch; 1900 war weit in der Vergangenheit und 2100 ist nun, in einer Weile.
Adám

3
@ RickHitchcock Es kann sehr gut sein, dass der ursprüngliche Lotus 1-2-3 Y2K nicht handhaben konnte, und so entschied sich Microsoft, dieses eine Problem zu imitieren, aber ansonsten richtig zu bleiben. Btw, die Legacy - Leben auf: hat von .NET OADate Epoche 1899-12- 30 , so dass es auf alle mit Excel in einer Reihe aufstellen, sondern den ersten beiden Monaten des Jahres 1900, aber das erfordert dies DayOfWeekVerfahren , weil die ursprüngliche Epoche, 1899-12-30 (oder das fiktive 1900-01-00) wurde so gewählt, dass der Wochentag einfach der Mod-7 der Tageszahl war, aber das funktioniert nicht mit 1899-12-30.
Adám

4
Hier ist die Geschichte hinter dem "Warum" von Excel-Daten: Joel über Software: My First BillG Review . Informatives (und unterhaltsames) Lesen.
BradC

Antworten:


13

Excel, 3 (+7?)

=A1

mit format

yyy/m/d

Reiner Hafen


Das Ausgabeformat kann natürlich je nach Gebietsschema variieren.
Adám

2
Dies funktioniert nur in Excel für Windows. Excel für Mac hat ein Zahlensystem, das mit Daten ab 1904 und nicht ab 1900 beginnt. Es gibt kein Datum für ein Jahr im Jahr 1900 an, die Teil der Testfälle sind. Möglicherweise möchten Sie angeben, dass dies Excel für Windows ist.
Keeta - wieder Monica

1
@Keeta Damit dies funktioniert auf Excel für Mac, einfach deaktivieren Sie „Use 1904 - Datumssystem“ in den Einstellungen .
BradC

1
@BradC Obwohl dies zutrifft, ist jede Änderung an der Standardkonfiguration eines Programms in Ordnung, ABER muss in der Antwort enthalten sein. Ich kommentiere dies, um die Antwort zu verbessern. Ich würde sagen, dass Sie entweder den Namen in Excel für Windows ändern, die Einschränkung hinzufügen oder zu OpenOffice Calc (oder ähnlichem, da auch der Fehler absichtlich enthalten ist) wechseln. codegolf.meta.stackexchange.com/questions/10037/…
Keeta - wieder Monica

6

k (kdb + 3,5), 55 54 51 50 Bytes

{$(`1900.01.00`1900.02.29,"d"$x-36526-x<60)0 60?x}

Fügen Sie zum Testen diese Zeile in die q-Konsole ein:

k)-1@{$(`1900.01.00`1900.02.29,"d"$x-36526-x<60)0 60?x}'0 1 2 59 60 61 100 1000 10000 100000;

die Ausgabe sollte sein

1900.01.00
1900.01.01
1900.01.02
1900.02.28
1900.02.29
1900.03.01
1900.04.09
1902.09.26
1927.05.18
2173.10.14

{ } ist eine Funktion mit Argument x

0 60?x Index von x unter 0 60oder 2, wenn nicht gefunden

ˋ1900.01.00ˋ1900.02.29 eine Liste von zwei Symbolen

, anhängen

"d"$ in ein Datum umgewandelt

x-36526 Anzahl der Tage seit 1900 (anstelle des Standardwerts 2000)

- x<60 korrigieren Sie den Sprungfehler von Excel

(ˋ1900.01.00ˋ1900.02.29,"d"$x-36526-x<60)@ 0 60?xGegenüberstellung bedeutet Indizierung - das "@" in der Mitte ist implizit

$ In String konvertieren


1
Für eine andere Version von k (k5 / k6, denke ich) {$[x;$`d$x-65746;"1900.01.00"]} scheint es zu funktionieren . Ich gehe davon aus, dass irgendwo etwas überläuft 100000.
zgrep

@zgrep Du solltest posten, da K-Versionen grundsätzlich völlig unterschiedliche Sprachen sind.
Adám


3

JavaScript (ES6),  89 82  77 Byte

Gespeichert  7  12 Bytes dank @tsh

n=>(p=n>60?'':19)+new Date(p*400,0,n-!p||1).toJSON().slice(p/9,10-!n)+(n&&'')

Probieren Sie es online!


n=>n?n-60?new Date(1900,0,n-(n>60)).toJSON().slice(0,10):'1900-02-29':'1900-01-00'
Dienstag,

@tsh Das ist in der Tat viel besser. Vielen Dank. (Auch ich frage mich, ob dieser Ansatz irgendwie Golf gespielt werden könnte.)
Arnauld

Ich finde nur heraus, new Date(0,0,1)ist das gleiche wie new Date(1900,0,1). Also 190spart entfernen 3 Bytes. Und ...
Dienstag,

2
77 Bytes:n=>(p=n>60?'':19)+new Date(p*400,0,n-!p||1).toJSON().slice(p/9,10-!n)+(n&&'')
tsh

Muss es in GMT0 / -x ausgeführt werden?
14 m²,

2

Sauber , 205 189 Bytes

import StdEnv
a=30;b=31;c=1900;r=rem
@m=sum(take m(?c))
?n=[b,if(n>c&&(r n 4>0||r n 100<1&&r n 400>0))28 29,b,a,b,a,b,b,a,b,a,b: ?(n+1)]
$n#m=while(\m= @m<n)inc 0-1
=(c+m/12,1+r m 12,n- @m)

Probieren Sie es online!


1
Erste Antwort, die keine integrierte Datumsverarbeitung verwendet. Nett!
Adám


1

APL (Dyalog Classic) , 31 Byte

Anonyme implizite Präfixfunktion. Rückgabedatum als[Y,M,D]

3↑×-60∘≠)+32NQ#263,60∘>+⊢-×

Probieren Sie es online!

× Vorzeichen des Datumscodes

⊢- subtrahiere das vom Argument (dem Datumscode)

60∘>+ Inkrementieren, wenn der Datumscode über sechzig liegt

2⎕NQ#263, Verwenden Sie dies als unmittelbares Argument für "Ereignis 263" (IDN bis heute).
IDN entspricht dem Datumscode von Excel, jedoch ohne den 29. Februar 1900, und der Tag vor dem 1. Januar 1900 ist der 31. Dezember 1899

3↑ nimm die ersten drei Elemente davon (das vierte ist der Wochentag)

()+ Fügen Sie Folgendes hinzu:

60∘≠ 0, wenn der Datumscode 60 ist; 1, wenn der Datumscode nicht 60 ist

×- subtrahieren Sie das vom Vorzeichen des Datumscodes

¯3↑ nimm die letzten drei Elemente (es gibt nur ein), die mit (zwei) Nullen aufgefüllt sind

entwickelt zusammen mit @ Adám im Chat


1

C # (.NET Core) , 186 bis 185 Byte

using System;class P{static void Main(){var i=int.Parse(Console.ReadLine());Console.Write((i==0|i==60)?$"1900-{i%59+1}-{i%31}":DateTime.FromOADate(i+(i<60?1:0)).ToString("yyyy-M-d"));}}

Probieren Sie es online!


-1 Byte durch Ersetzen des OR-Operators (||) durch den binären OR-Operator (|).



0

T-SQL, 141 95 94 Bytes

SELECT IIF(n=0,'1/0/1900',IIF(n=60,'2/29/1900',
FORMAT(DATEADD(d,n,-IIF(n<60,1,2)),'d')))FROM i

Zeilenumbruch dient nur der Lesbarkeit.

Eingang über vorbestehenden Tabelle entnommen i mit ganzzahligem Feld n , pro unseren IO - Standards .

SQL verwendet einen ähnlichen (aber korrigierten) 1-1-1900 Ausgangspunkt für sein internes Datumsformat, so dass ich ihn im nur um 1 oder 2 Tage versetzen muss DATEADD Funktion .

SQL kann keine Spalte ausgeben, die eine Mischung aus Datums- und Zeichenwerten enthält, sodass ich den FORMATBefehl nicht auslassen kann (da er dann versuchen würde, 1/0/1900in ein Datum zu konvertieren , das natürlich ungültig ist).

Das Schöne an SQL ist, dass ich alle Eingabewerte in die Tabelle laden und gleichzeitig ausführen kann. Meine (US) Lokalität hat standardmäßig ein m/d/yyyyDatumsformat:

n       output
0       1/0/1900
1       1/1/1900
2       1/2/1900
59      2/28/1900
60      2/29/1900
61      3/1/1900
100     4/9/1900
1000    9/26/1902
10000   5/18/1927
43432   11/28/2018
100000  10/14/2173

BEARBEITEN : 46 Bytes gespart, indem zu einem verschachtelten IIF()anstatt des viel ausführlicheren gewechselt wurde CASE WHEN.

BEARBEITEN 2 : Speichert ein weiteres Byte, indem das -vor dem IIF.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.