Occurrences de date


9

Compte tenu de trois entiers non négatifs y, met d(dont au moins un doit être positif) et une date valide une année positive (dans tout format raisonnable qui comprend l'année, le mois et le jour, et aucune information supplémentaire), la sortie du date correspondant à des yannées, des mmois et des djours après la date d'origine.

Le calendrier grégorien doit être utilisé pour toutes les dates (même les dates antérieures à l'adoption du calendrier grégorien).

La méthode de calcul de la prochaine date est la suivante:

  1. Ajouter yà l'année
  2. Ajouter mau mois
  3. Normaliser la date en appliquant des survols (par exemple 2018-13-01-> 2019-01-01)
  4. Si le jour est passé le dernier jour du mois, remplacez-le par le dernier jour du mois (par exemple 2018-02-30-> 2018-02-28)
  5. Ajouter dà la journée
  6. Normaliser la date en appliquant des survols (par exemple 2019-01-32-> 2019-02-01)

Les années bissextiles (années divisibles par 4, mais non divisibles par 100 sauf si elles sont également divisibles par 400) doivent être traitées de manière appropriée. Toutes les entrées et sorties seront dans la plage entière représentable de votre langue.

Cas de test

Les cas de test sont fournis au format input => output, où se inputtrouve un objet JSON.

{"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

Vous pouvez utiliser ce JSFiddle pour les tests.

Il s'agit de , donc la solution la plus courte (dans chaque langue) l'emporte.



2
@LuisfelipeDejesusMunoz Le format d'entrée n'est pas important, comme c'est la norme ici sur PPCG.
Mego

Y a-t-il une restriction aux limites supérieures de y, met d(par exemple pourrait dêtre 2147483000?)
ErikF

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

1
Qu'en est-il des formats de sortie? Pouvons-nous sortir un objet date? Peut-on prendre un objet date?
Asone Tuhid

Réponses:


3

C (gcc) , 291 octets

Celui-ci était assez amusant pour obtenir les mêmes valeurs que le JS intégré.

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]++;}

Essayez-le en ligne!

Non-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
}

Essayez-le en ligne!



1

perl -MDate :: Calc =: tous -E, 28 octets

$,=$";say Add_Delta_YMD@ARGV

Cela prend 6 arguments: l'année, le mois et la date (comme arguments séparés), et le nombre d'années, de mois et de jours à ajouter.


2
Cela ne concerne pas la "règle 4" excentrique de la tâche, donc échoue certains des cas de test - par exemple, perl -MDate::Calc=:all -E '$,=$";say Add_Delta_YMD@ARGV' -- 2000 2 29 1 0 0retourne 2001 3 1au lieu de ce 2001 2 28que l'OP attend (cas de test 6).
sundar

1

R , 88 octets

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}

Essayez-le en ligne!

Une fonction qui prend 3 arguments ( Y,M,D) pour la date et 3 autres arguments ( y,m,d) pour les valeurs à ajouter.

La sortie est livré avec Prepended 12:00:00 GMTqui est le format par défaut pour ISOdate« s


1

Perl 6 ,  60 50 45  44 octets

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

Testez-le (60) L'
entrée est( "2000-02-29", year => 1, month => 0, day => 0 )


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

Testez-le (50) L'
entrée est( Date.new("2000-02-29"), year => 1, month => 0, day => 0 )


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

Testez-le (45) L'
entrée est ( Date.new("2000-02-29"), %( year => 1 ) )
(pas besoin d'inclure des clés avec une valeur de 0)


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

Testez-le (44) L'
entrée est( Date.new("2000-02-29"), year => 1 )

Étendu:

{  # 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
  $/
}

Vous pouvez supprimer l'espace avant lefor
Jo King


1

Java 8, 51 octets

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

L'entrée ( s) et la sortie sont toutes les deux java.time.LocalDate.

Essayez-le en ligne.

Explication:

(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 octets

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

Utilise le lubridatepackage. L' %m+%opérateur infixe est le sucre de la add_with_rollbackfonction qui implémente essentiellement ce que la question demande.

TIO n'en a pas lubridate, vous pouvez donc l' essayer ici à la place avec f <-ajouté à la fonction ci-dessus avec des cas de test:

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

Vous pouvez enregistrer enregistrer deux octets avec: function(x,y)x%m+%period(y,c("ye","mo","d")) require(lubridate)(nécessite une fonction hors fonction)
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))]

Essayez-le en ligne!

Prend les entrées via les arguments de ligne de commande dans l'ordre: ancienne année, ancien mois, ancien jour. changement d'année, changement de mois, changement de jour. Sort une chaîne comme Wed Feb 28 00:00:00 UTC 2018stdout.


0

PHP , 203 octets

<?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');

Pour l'exécuter:

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

Exemple:

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

Ou essayez-le en ligne!

Tests: Essayez-le en ligne!


0

T-SQL, 53 octets

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

Je ne suis pas sûr que cela soit important, mais j'applique l'ajustement de l'année, suivi de l'ajustement du mois, suivi du jour. Toutes les valeurs de test sont vérifiées.

Selon nos normes d'E / S , l'entrée est tirée d'une table préexistante t avec le champ de date a et les champs entiers y , m et d .

Notez que ce n'est pas la capitalisation qui importe entre les codes de type de date ( D , M et Y ) et mes valeurs d'entrée ( d , m et y ), c'est simplement l'ordre des paramètres dans la DATEADDfonction SQL .


1
Est-ce que cela passe le cas de test 6? Puisqu'il 2001 3 12001 2 28
n'implémente

@sundar On dirait que vous avez raison; Je pensais avoir réussi tous les cas de test. Je vais voir si cela peut être corrigé ...
BradC
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.