Datum Vorkommen


9

Gegeben drei nicht negative ganze Zahlen y, mund d(von denen mindestens einer muss positiv sein) und ein gültiges Datum mit einem positiven Jahr (in jedem vernünftigen Format , das das Jahr enthält, Monat und Tag, und keine weiteren Informationen), Ausgabe der Datum, das yJahre, mMonate und dTage nach dem ursprünglichen Datum liegt.

Der Gregorianische Kalender ist für alle Daten zu verwenden (auch Daten vor der Annahme des Gregorianischen Kalenders).

Die Methode zur Berechnung des nächsten Datums lautet wie folgt:

  1. yZum Jahr hinzufügen
  2. In mdem Monat
  3. Normalisieren Sie das Datum durch Anwenden von Rollovers (z. B. 2018-13-01-> 2019-01-01).
  4. Wenn der Tag nach dem letzten Tag des Monats liegt, ändern Sie ihn auf den letzten Tag des Monats (z. B. 2018-02-30-> 2018-02-28).
  5. dZum Tag hinzufügen
  6. Normalisieren Sie das Datum durch Anwenden von Rollovers (z. B. 2019-01-32-> 2019-02-01).

Schaltjahre (Jahre, die durch 4 teilbar sind, aber nicht durch 100 teilbar sind, es sei denn, sie sind auch durch 400 teilbar) müssen angemessen behandelt werden. Alle Ein- und Ausgänge liegen im darstellbaren Ganzzahlbereich Ihrer Sprache.

Testfälle

Die Testfälle werden in dem Format zur Verfügung gestellt input => output, in dem inputein JSON - Objekt ist.

{"date":"2018-01-01","add":{"d":1}} => 2018-01-02
{"date":"2018-01-01","add":{"M":1}} => 2018-02-01
{"date":"2018-01-01","add":{"Y":1}} => 2019-01-01
{"date":"2018-01-30","add":{"M":1}} => 2018-02-28
{"date":"2018-01-30","add":{"M":2}} => 2018-03-30
{"date":"2000-02-29","add":{"Y":1}} => 2001-02-28
{"date":"2000-02-29","add":{"Y":4}} => 2004-02-29
{"date":"2000-01-30","add":{"d":2}} => 2000-02-01
{"date":"2018-01-01","add":{"Y":2,"M":3,"d":4}} => 2020-04-05
{"date":"2018-01-01","add":{"Y":5,"M":15,"d":40}} => 2024-05-11

Sie können diese JSFiddle zum Testen verwenden.

Dies ist , also gewinnt die kürzeste Lösung (in jeder Sprache).


Sandbox Post (gelöscht)
Mego

2
@LuisfelipeDejesusMunoz Das Eingabeformat ist nicht wichtig, wie es hier bei PPCG üblich ist.
Mego

Gibt es eine Beschränkung auf die oberen Grenzen y, mund d(zB könnte d2147483000 sein?)
ErikF

@ErikFAll inputs and outputs will be within the representable integer range of your language.
Mego

1
Was ist mit Ausgabeformaten? Können wir ein Datumsobjekt ausgeben? Können wir ein Datumsobjekt nehmen?
Asone Tuhid

Antworten:


3

C (gcc) , 291 Bytes

Es hat ziemlich viel Spaß gemacht, die gleichen Werte wie das eingebaute JS zurückzugeben.

z,m=0xEEFBB3;int*y;g(){z=28+(m>>y[1]*2&3)+!(y[1]-1)*(!(*y%4)&&(*y%100)||!(*y%400));}h(a){z=(a>g())?g():a;}j(){*y+=y[1]/12;y[1]%=12;y[2]=h(y[2]);}f(int*a){y=a+6;for(z=0;z<3;z++)y[z]=a[z];y[1]--;j();*y+=a[3];y[1]+=a[4];j();y[2]+=a[5];for(;y[2]>h(y[2]);(y[1]=++y[1]%12)||++*y)y[2]-=g();y[1]++;}

Probieren Sie es online aus!

Nicht Golf:

// De No Oc Se Au Jl Jn Ma Ap Mr Fe Ja
// 31 30 31 30 31 31 30 31 30 31 28 31 = Month length
// 11 10 11 10 11 11 10 11 10 11 00 11 = Offset (2-bit representation)
//   E     E     F     B     B     3   = Hex representation

int m=0xEEFBB3; // Month lengths-28 in reverse order, stored as 2 bits/month
int *y; // Pointer to the output date, shared as a global between calls

// Regenerate month length and add leap day
int days_month(void) { 
  return 28+(m>>y[1]*2&3)+!(y[1]-1)*(!(*y%4)&&(*y%100)||!(*y%400));
}

int calendar_day(int day) { return day>days_month()?days_month():day; }

void truncate_date(void) {
  *y+=y[1]/12; y[1]%=12;
  y[2]=calendar_day(y[2]);
}

void f(int *a) {
  int z;
  y=a+6;
  for(z=0;z<3;z++)y[z]=a[z];y[1]--; // Convert month to 0-based
  truncate_date();
  *y+=a[3]; y[1]+=a[4]; truncate_date();
  y[2]+=a[5];
  for(;y[2]>calendar_day(y[2]);(y[1]=++y[1]%12)||++*y)
    y[2]-=days_month();
  y[1]++; // Return month to 1-based
}

Probieren Sie es online aus!



1

perl -MDate :: Calc =: all -E, 28 Bytes

$,=$";say Add_Delta_YMD@ARGV

Dies erfordert 6 Argumente: das Eingabejahr, den Monat und das Datum (als separate Argumente) sowie die Anzahl der Jahre, Monate und Tage, die hinzugefügt werden müssen.


2
Dies betrifft nicht die skurrile "Regel 4" der Aufgabe, so dass einige der Testfälle fehlschlagen - z. B. perl -MDate::Calc=:all -E '$,=$";say Add_Delta_YMD@ARGV' -- 2000 2 29 1 0 0Rückgabe 2001 3 1statt 2001 2 28wie vom OP erwartet (Testfall 6).
Sundar - Reinstate Monica

1

R 88 Bytes

function(Y,M,D,y,m,d,o=M+m){while(is.na(x<-ISOdate(Y+y+o%/%12,o%%12,D)))D=D-1;x+864e2*d}

Probieren Sie es online aus!

Eine Funktion, die 3 Argumente ( Y,M,D) für das Datum und 3 weitere Argumente ( y,m,d) für die hinzuzufügenden Werte verwendet.

Die Ausgabe wird mit vorangestelltem 12:00:00 GMTFormat geliefert. Dies ist das Standardformat für ISOdate's


1

Perl 6 ,  60 50 45  44 Bytes

{Date.new($^a).later(:$:year).later(:$:month).later(:$:day)}

Test it (60)
Eingang ist( "2000-02-29", year => 1, month => 0, day => 0 )


{$^a.later(:$:year).later(:$:month).later(:$:day)}

Test it (50)
Eingang ist( Date.new("2000-02-29"), year => 1, month => 0, day => 0 )


{$/=$^a;$/.=later(|$_) for |[R,] $^b.sort;$/}

Test it (45)
Eingabe ist ( Date.new("2000-02-29"), %( year => 1 ) )
(Es müssen keine Schlüssel mit dem Wert 0 eingefügt werden)


{$/=$^a;$/.=later(|$_) for |[R,] %_.sort;$/}

Test it (44)
Eingang ist( Date.new("2000-02-29"), year => 1 )

Erweitert:

{  # bare block lambda

  $/ = $^a; # store only positional param into a modifiable scalar
            # (params are readonly by default)


  # do a loop over the data to add

  $/ .= later(    # add using Date.later()
    |$_           # turn current iterated Pair into a named parameter
  )

    for

      |           # flatten so that `for` will iterate

        [R,]      # shorter than `reverse` (year=>1, month=>0, day=>0)

          %_.sort # sort the named arguments (day=>0, month=>0, year=>1)
  ;

  # return new Date
  $/
}

Sie können das Leerzeichen vor demfor
Jo King


1

Java 8, 51 Bytes

(s,y,m,d)->s.plusYears(y).plusMonths(m).plusDays(d)

Input ( s) und Output sind beide java.time.LocalDate.

Probieren Sie es online aus.

Erläuterung:

(s,y,m,d)->        // Method with LocalDate and 3 int parameters and LocalDate return-type
  s.plusYears(y)   //  Add the years to the input start-Date
   .plusMonths(m)  //  Add the months as well
   .plusDays(d)    //  And add the days as well

1

R , 65 Bytes

function(x,y){require(lubridate)
x%m+%period(y,c("ye","mo","d"))}

Verwendet das lubridatePaket. Der %m+%Infix-Operator ist Zucker für die add_with_rollbackFunktion, die im Wesentlichen implementiert, was die Frage verlangt.

TIO hat nicht lubridateso Sie können es hier stattdessen versuchen , mit f <-voran auf die Funktion oben zusammen mit Testfällen:

f(as.Date("2018-01-01"),c(0,0,1))
f(as.Date("2018-01-01"),c(0,1,0))
f(as.Date("2018-01-01"),c(1,0,0))
f(as.Date("2018-01-30"),c(0,1,0))
f(as.Date("2018-01-30"),c(0,2,0))
f(as.Date("2000-02-29"),c(1,0,0))
f(as.Date("2000-02-29"),c(4,0,0))
f(as.Date("2000-01-30"),c(0,0,2))
f(as.Date("2018-01-01"),c(2,3,4))
f(as.Date("2018-01-01"),c(5,15,40))

Sie können speichern, speichern Sie zwei Bytes mit: function(x,y)x%m+%period(y,c("ye","mo","d")) require(lubridate)(erfordern außerhalb der Funktion)
JayCe

0

Bash , 150 149 Bytes

a=$2+$5-1+b
y=$1+$4+a/12
m=1+a%12
d=date
$d -d@$[$($d +%s+$6*86400 -d$[y]-$[m]-$($d +$3%n%d -d@$[`b=1;$d +%s-86400 -d$[y]-$[m]-1`]|sort -n|head -1))]

Probieren Sie es online aus!

Nimmt Eingaben über Befehlszeilenargumente in der Reihenfolge vor: altes Jahr, alter Monat, alter Tag. Jahreswechsel, Monatswechsel, Tageswechsel. Gibt eine Zeichenfolge wie Wed Feb 28 00:00:00 UTC 2018stdout aus.


0

PHP , 203 Bytes

<?list(,$a,$y,$m,$d)=$argv;$b=new DateTime($a);$j=$b->format('j');$b->modify("+$y year +$m month");$j==$b->format('j')?:$b->modify('last day of last month');$b->modify("+$d day");echo$b->format('Y-m-d');

Um es auszuführen:

php -n <filename> <date> <y> <m> <d>

Beispiel:

php -n date_occurrences.php 2018-01-01 5 15 40

Oder probieren Sie es online!

Tests: Probieren Sie es online aus!


0

T-SQL, 53 Bytes

SELECT DATEADD(D,d,DATEADD(M,m,DATEADD(Y,y,a)))FROM t

Ich bin mir nicht sicher, ob es wichtig ist, aber ich wende die Jahresanpassung an, gefolgt von der Monatsanpassung, gefolgt vom Tag. Alle Testwerte werden ausgecheckt.

Gemäß unseren E / A-Standards wird die Eingabe aus einer bereits vorhandenen Tabelle t mit den Datumsfeldern a und den ganzzahligen Feldern y , m und d übernommen .

Interessanterweise ist es nicht die Groß- und Kleinschreibung, die zwischen den Datumstypcodes ( D , M und Y ) und meinen Eingabewerten ( d , m und y ) von Bedeutung ist, sondern lediglich die Reihenfolge der Parameter in der SQL- DATEADDFunktion .


1
Besteht dieser Testfall 6? Da es Regel 4 nicht implementiert, denke ich, dass es 2001 3 1statt 2001 2 28für Eingabe 6 geben würde .
Sundar - Reinstate Monica

@ Sundar Sieht aus wie Sie richtig sind; Ich dachte, ich hätte alle Testfälle bestanden. Ich werde sehen, ob es behoben werden kann ...
BradC
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.