Tanggal Kemunculan

9

Mengingat tiga bilangan bulat non-negatif y, mdan d(yang setidaknya satu harus positif) dan tanggal yang valid dengan tahun positif (dalam format yang wajar yang mencakup tahun, bulan, hari, dan tidak ada informasi tambahan), output tanggal yaitu ytahun, mbulan, dan dhari setelah tanggal asli.

Kalender Gregorian harus digunakan untuk semua tanggal (bahkan tanggal sebelum adopsi kalender Gregorian).

Metode untuk menghitung tanggal berikutnya adalah sebagai berikut:

  1. Tambahkan yke tahun
  2. Tambahkan mke bulan
  3. Normalisasi tanggal dengan menerapkan rollover (mis 2018-13-01- - 2019-01-01)
  4. Jika hari itu melewati hari terakhir bulan itu, ubah hari itu menjadi hari terakhir di bulan itu (mis. 2018-02-30-> 2018-02-28)
  5. Tambahkan dke hari itu
  6. Normalisasi tanggal dengan menerapkan rollover (mis 2019-01-32- - 2019-02-01)

Tahun kabisat (tahun habis dibagi 4, tetapi tidak habis dibagi 100 kecuali juga habis dibagi 400) harus ditangani dengan tepat. Semua input dan output akan berada dalam kisaran integer yang dapat diwakili dari bahasa Anda.

Uji Kasus

Test case disediakan dalam format input => output, di mana inputobjek 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

Anda dapat menggunakan JSFiddle ini untuk pengujian.

Ini adalah , jadi solusi terpendek (dalam setiap bahasa) menang.

Mego
sumber
Posting Sandbox (dihapus)
Mego
2
@LuisfelipeDejesusMunoz Format input tidak penting, seperti norma di PPCG.
Mego
Apakah ada batasan pada batas atas y, mdan d(misalnya bisa d2147483000?)
ErikF
@ErikFAll inputs and outputs will be within the representable integer range of your language.
Mego
1
Bagaimana dengan format output? Bisakah kita menampilkan objek tanggal? Bisakah kita mengambil objek kencan?
Asone Tuhid

Jawaban:

3

C (gcc) , 291 byte

Yang ini cukup menyenangkan untuk mendapatkan kembali nilai yang sama dengan JS builtin.

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

Cobalah online!

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

Cobalah online!

ErikF
sumber
249 byte
ceilingcat
1

perl -MDate :: Calc =: semua -E, 28 byte

$,=$";say Add_Delta_YMD@ARGV

Ini membutuhkan 6 argumen: tahun input, bulan dan tanggal (sebagai argumen terpisah), dan jumlah tahun, bulan dan hari untuk ditambahkan.


sumber
2
Ini tidak berurusan dengan "aturan 4" yang unik dari tugas, jadi gagal beberapa kasus uji - misalnya, perl -MDate::Calc=:all -E '$,=$";say Add_Delta_YMD@ARGV' -- 2000 2 29 1 0 0mengembalikan 2001 3 1bukan 2001 2 28seperti yang diharapkan OP (kasus uji 6).
sundar - Reinstate Monica
1

R , 88 byte

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}

Cobalah online!

Fungsi yang mengambil 3 argumen ( Y,M,D) untuk tanggal, dan 3 argumen lainnya ( y,m,d) untuk nilai yang akan ditambahkan.

Output dilengkapi dengan dibubuhkan di awal 12:00:00 GMTyang merupakan format default untuk ISOdate's

menggali semua
sumber
1

Perl 6 ,  60 50 45  44 byte

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

Uji (60)
inputnya( "2000-02-29", year => 1, month => 0, day => 0 )


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

Uji (50)
inputnya( Date.new("2000-02-29"), year => 1, month => 0, day => 0 )


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

Mengujinya (45)
Inputnya adalah ( Date.new("2000-02-29"), %( year => 1 ) )
(Tidak perlu memasukkan kunci dengan nilai 0)


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

Uji (44)
Inputnya adalah( Date.new("2000-02-29"), year => 1 )

Diperluas:

{  # 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
sumber
Anda dapat menghapus ruang sebelumfor
Jo King
1

Java 8, 51 byte

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

Input ( s) dan output keduanya java.time.LocalDate.

Cobalah online.

Penjelasan:

(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
sumber
1

R , 65 byte

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

Menggunakan lubridatepaket. The %m+%Operator infiks adalah gula untuk add_with_rollbackfungsi yang pada dasarnya mengimplementasikan apa pertanyaan meminta.

TIO tidak memiliki lubridatesehingga Anda dapat Coba Di Sini Sebagai gantinya dengan f <-ditambahkan ke fungsi di atas bersama dengan kasus uji:

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
sumber
Anda dapat menyimpan save dua byte dengan: function(x,y)x%m+%period(y,c("ye","mo","d")) require(lubridate)(memerlukan outisde of function)
JayCe
0

Bash , 150 149 byte

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

Cobalah online!

Mengambil input melalui argumen baris perintah secara berurutan: tahun tua, bulan tua, hari tua. perubahan tahun, perubahan bulan, perubahan hari. Menghasilkan string seperti Wed Feb 28 00:00:00 UTC 2018ke stdout.

wastl
sumber
0

PHP , 203 byte

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

Untuk menjalankannya:

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

Contoh:

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

Atau Coba online!

Tes: Coba online!

Night2
sumber
0

T-SQL, 53 Bytes

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

Saya tidak yakin itu penting, tapi saya menerapkan penyesuaian Tahun, diikuti oleh penyesuaian Bulan, diikuti oleh Hari. Semua nilai tes dicoba.

Sesuai standar IO kami , input diambil dari tabel t yang sudah ada dengan bidang tanggal a dan bidang bilangan bulat y , m , dan d .

Perhatikan dengan menarik bahwa itu bukan huruf besar yang penting antara kode tipe tanggal ( D , M , dan Y ) dan nilai input saya ( d , m , dan y ) hanya urutan parameter dalam DATEADDfungsi SQL .

BradC
sumber
1
Apakah ini lulus uji kasus 6? Karena tidak menerapkan Rule 4, saya pikir itu akan memberi 2001 3 1alih-alih 2001 2 28untuk input 6.
sundar - Reinstate Monica
@sundar Sepertinya Anda benar; Saya pikir saya telah lulus semua test case. Saya akan melihat apakah itu bisa diperbaiki ...
BradC