Дата виникнення


9

З огляду на три невід'ємні цілі числа y, mі d(з яких принаймні один повинен бути позитивним) і коректну дату з позитивним року (в будь-якому зручному форматі , який включає в себе рік, місяць і день, і ніякої додаткової інформації), вихід на дата, яка є yроками, mмісяцями та dднями після початкової дати.

Григоріанський календар слід використовувати для всіх дат (навіть дат до прийняття григоріанського календаря).

Метод обчислення наступної дати такий:

  1. Додайте yдо року
  2. Додайте mдо місяця
  3. Нормалізуйте дату, застосувавши перекидання (наприклад 2018-13-01-> 2019-01-01)
  4. Якщо день минув останній день місяця, змініть його на останній день місяця (наприклад 2018-02-30-> 2018-02-28)
  5. Додати dв день
  6. Нормалізуйте дату, застосувавши перекидання (наприклад 2019-01-32-> 2019-02-01)

Випускні роки (роки, що діляться на 4, але не діляться на 100, якщо також не поділяються на 400), повинні оброблятися належним чином. Усі входи та виходи знаходяться в межах цілого діапазону вашої мови.

Випробування

Тестові приклади надаються у форматі input => output, де inputє об’єкт 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

Ви можете використовувати цю JSFiddle для тестування.

Це є , тому найкоротше рішення (кожною мовою) виграє.



2
@LuisfelipeDejesusMunoz Формат введення не важливий, як це норма в PPCG.
Мего

Чи є обмеження у верхніх межах y, mі d(наприклад, це може dбути 2147483000?)
ErikF

@ErikFAll inputs and outputs will be within the representable integer range of your language.
Мего

1
Що з вихідними форматами? Чи можемо ми вивести об’єкт дати? Чи можемо ми взяти об’єкт дати?
Асона Тухід

Відповіді:


3

C (gcc) , 291 байт

Це було дуже весело отримувати повернення тих же значень, що і JS вбудований.

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

Спробуйте в Інтернеті!

Без гольфу:

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

Спробуйте в Інтернеті!



1

perl -MDate :: Calc =: all -E, 28 байт

$,=$";say Add_Delta_YMD@ARGV

Для цього потрібно 6 аргументів: рік введення, місяць і дата (як окремі аргументи), а також кількість років, місяців і днів для додавання.


2
Це не стосується химерного "правила 4" завдання, тому не вдається деякі тестові випадки - наприклад, perl -MDate::Calc=:all -E '$,=$";say Add_Delta_YMD@ARGV' -- 2000 2 29 1 0 0повертається 2001 3 1замість того, 2001 2 28як очікує ОП (тестовий випадок 6).
sundar

1

R , 88 байт

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}

Спробуйте в Інтернеті!

Функція, яка бере 3 аргументи ( Y,M,D) для дати та інші 3 аргументи ( y,m,d) для значень, які потрібно додати.

Вихід 12:00:00 GMTмає попередньо встановлений формат, який є типовим для ISOdate's


1

Perl 6 ,  60 50 45  44 байт

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

Перевірте це (60)
Вхід є( "2000-02-29", year => 1, month => 0, day => 0 )


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

Перевірте його (50)
Вхід є( Date.new("2000-02-29"), year => 1, month => 0, day => 0 )


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

Перевірте його (45)
Вхід є ( Date.new("2000-02-29"), %( year => 1 ) )
(Не потрібно включати ключі зі значенням 0)


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

Перевірте (44)
Вхід є( Date.new("2000-02-29"), year => 1 )

Розширено:

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

Ви можете видалити пробіл доfor
Jo King


1

Java 8, 51 байт

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

Вхід ( s) і вихід є обома java.time.LocalDate.

Спробуйте в Інтернеті.

Пояснення:

(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 байт

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

Використовує lubridateпакет. Оператор %m+%інфіксації - це цукор для add_with_rollbackфункції, яка по суті реалізує те, про що задається питання.

TIO не має , lubridateтак що ви можете спробувати це тут Замість з f <-префіксом функції вище , а також тестів:

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

Ви можете зберегти два байти за допомогою: function(x,y)x%m+%period(y,c("ye","mo","d")) require(lubridate)(вимагає перевищення функції)
JayCe

0

Баш , 150 149 байт

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

Спробуйте в Інтернеті!

Вводиться через аргументи командного рядка в порядку: старий рік, старий місяць, старий день. зміна року, зміна місяця, зміна дня. Виводить рядок, як Wed Feb 28 00:00:00 UTC 2018stdout.



0

T-SQL, 53 байти

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

Я не впевнений, що це має значення, але я застосовую коригування року, за яким слід коригування місяця, а потім День. Усі тестові значення перевіряються.

Відповідно до наших стандартів IO , вхід береться з попередньо існуючої таблиці t з датою поля a і цілими полями y , m та d .

Зверніть увагу , що цікаво , що це не капіталізація , що має значення між кодами дати типу ( D , M і Y ) і моїми вхідними значеннями ( д , м , і у ) її просто порядку параметрів в SQL DATEADDфункції .


1
Чи проходить цей тест 6? Оскільки воно не реалізує правило 4, я думаю, що він дасть 2001 3 1замість 2001 2 28введення 6.
sundar - Поновіть Моніку

@sundar Схоже, ти маєш рацію; Я думав, що пройшов усі тестові справи. Я побачу, чи можна це виправити ...
BradC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.