Fecha de ocurrencia

9

Dado tres números enteros no negativos y, my d(de los cuales al menos uno debe ser positivo) y una fecha válida con un año positivo (en cualquier formato razonable, que incluye el año, mes y día, y no hay información adicional), la salida de la fecha que es yaños, mmeses y ddías después de la fecha original.

El calendario gregoriano se debe utilizar para todas las fechas (incluso las fechas anteriores a la adopción del calendario gregoriano).

El método para calcular la próxima fecha es el siguiente:

  1. Añadir yal año
  2. Agregar mal mes
  3. Normalice la fecha aplicando reinversiones (por ejemplo, 2018-13-01-> 2019-01-01)
  4. Si el día ha pasado el último día del mes, cámbielo al último día del mes (por ejemplo, 2018-02-30-> 2018-02-28)
  5. Añadir dal día
  6. Normalice la fecha aplicando reinversiones (por ejemplo, 2019-01-32-> 2019-02-01)

Los años bisiestos (años divisibles por 4, pero no divisibles por 100 a menos que también sean divisibles por 400) deben manejarse adecuadamente. Todas las entradas y salidas estarán dentro del rango entero representable de su idioma.

Casos de prueba

Los casos de prueba se proporcionan en el formato input => output, donde inputes un objeto 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

Puede usar este JSFiddle para realizar pruebas.

Este es el , por lo que gana la solución más corta (en cada idioma).

Mego
fuente
Publicación de Sandbox (eliminada)
Mego
2
@LuisfelipeDejesusMunoz El formato de entrada no es importante, como lo es la norma aquí en PPCG.
Mego
¿Hay alguna restricción a los límites superiores de y, my d(por ejemplo, podría dser 2147483000?)
ErikF
@ErikFAll inputs and outputs will be within the representable integer range of your language.
Mego
1
¿Qué pasa con los formatos de salida? ¿Podemos generar un objeto de fecha? ¿Podemos tomar un objeto de fecha?
Asone Tuhid

Respuestas:

3

C (gcc) , 291 bytes

Este fue bastante divertido para obtener los mismos valores que el JS incorporado.

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

Pruébalo en línea!

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

Pruébalo en línea!

ErikF
fuente
249 bytes
ceilingcat
1

perl -MDate :: Calc =: todos -E, 28 bytes

$,=$";say Add_Delta_YMD@ARGV

Esto requiere 6 argumentos: el año, mes y fecha de entrada (como argumentos separados) y la cantidad de años, meses y días para agregar.


fuente
2
Esto no trata con la peculiar "regla 4" de la tarea, por lo que falla algunos de los casos de prueba, por ejemplo, perl -MDate::Calc=:all -E '$,=$";say Add_Delta_YMD@ARGV' -- 2000 2 29 1 0 0regresa en 2001 3 1lugar de lo 2001 2 28que espera el OP (caso de prueba 6).
sundar - Restablecer 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}

Pruébalo en línea!

Una función que toma 3 argumentos ( Y,M,D) para la fecha, y otros 3 argumentos ( y,m,d) para que se agreguen los valores.

La salida viene con antepuesto 12:00:00 GMTque es el formato por defecto de ISOdate's

digEmAll
fuente
1

Perl 6 ,  60 50 45  44 bytes

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

Pruébelo (60) La
entrada es( "2000-02-29", year => 1, month => 0, day => 0 )


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

Pruébelo (50) La
entrada es( Date.new("2000-02-29"), year => 1, month => 0, day => 0 )


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

Pruébelo (45) La
entrada es ( Date.new("2000-02-29"), %( year => 1 ) )
(No es necesario incluir claves con un valor de 0)


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

Pruébelo (44) La
entrada es( Date.new("2000-02-29"), year => 1 )

Expandido:

{  # 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
  $/
}
Brad Gilbert b2gills
fuente
Puede eliminar el espacio antes de lafor
Jo King
1

Java 8, 51 bytes

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

La entrada ( s) y la salida son ambas java.time.LocalDate.

Pruébalo en línea.

Explicación:

(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
Kevin Cruijssen
fuente
1

R , 65 bytes

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

Utiliza el lubridatepaquete. El %m+%operador infijo es el azúcar para la add_with_rollbackfunción que esencialmente implementa lo que pide la pregunta.

TIO no tiene, lubridatepor lo que puede probarlo aquí en lugar de f <-anteponer a la función anterior junto con casos de prueba:

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))
ngm
fuente
Puede guardar guardar dos bytes con: function(x,y)x%m+%period(y,c("ye","mo","d")) require(lubridate)(requiere salida de función)
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))]

Pruébalo en línea!

Toma entrada a través de argumentos de línea de comando en orden: año anterior, mes anterior, día anterior. cambio de año, cambio de mes, cambio de día. Emite una cadena como Wed Feb 28 00:00:00 UTC 2018stdout.

wastl
fuente
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');

Para ejecutarlo:

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

Ejemplo:

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

O Pruébelo en línea!

Pruebas: ¡ Pruébelo en línea!

Noche2
fuente
0

T-SQL, 53 bytes

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

No estoy seguro de que importe, pero estoy aplicando el ajuste Año, seguido del ajuste Mes, seguido del Día. Todos los valores de prueba están disponibles.

Por nuestros estándares IO , de entrada se toma de una preexistente tabla de t con el campo de la fecha una y campos enteros y , m , y d .

Observe de manera interesante que no es la capitalización lo que importa entre los códigos de tipo de fecha ( D , M e Y ) y mis valores de entrada ( d , m e y ) es simplemente el orden de los parámetros en la DATEADDfunción SQL .

BradC
fuente
1
¿Esto pasa el caso de prueba 6? Dado que no implementa la Regla 4, creo que daría en 2001 3 1lugar de la 2001 2 28entrada 6.
sundar - Restablecer Mónica
@sundar Parece que tienes razón; Pensé que había pasado todos los casos de prueba.
Veré