วันที่เกิดขึ้น


9

รับสาม integers เชิงลบy, mและd(ซึ่งอย่างน้อยหนึ่งต้องเป็นบวก) และวันที่ถูกต้องกับปีบวก (ในรูปแบบที่เหมาะสมใด ๆ ที่มีปีเดือนและวันที่และไม่มีข้อมูลเพิ่มเติม) เอาท์พุท วันที่คือyปีmเดือนและdวันหลังจากวันที่เดิม

ปฏิทิน Gregorian นั้นจะใช้สำหรับทุกวัน

วิธีการคำนวณวันที่ถัดไปมีดังนี้:

  1. เพิ่มyไปยังปี
  2. เพิ่มmไปยังเดือน
  3. ทำให้วันที่ปกติเป็นปกติโดยใช้ rollovers (เช่น2018-13-01-> 2019-01-01)
  4. หากวันนั้นผ่านวันสุดท้ายของเดือนให้เปลี่ยนเป็นวันสุดท้ายของเดือน (เช่น 2018-02-30 -> 2018-02-28)
  5. เพิ่ม dไปยังวันที่
  6. ทำให้วันที่ปกติเป็นปกติโดยใช้ rollovers (เช่น2019-01-32-> 2019-02-01)

Leap ปี (ปีหารด้วย 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 นี้สำหรับการทดสอบ

นี่คือ ดังนั้นทางออกที่สั้นที่สุด (ในแต่ละภาษา) จะชนะ


โพสต์ Sandbox (ลบแล้ว)
Mego

2
@LuisfelipeDejesusMunoz รูปแบบการป้อนข้อมูลไม่สำคัญเนื่องจากเป็นบรรทัดฐานที่นี่ใน PPCG
Mego

มีข้อ จำกัด ใด ๆ ในขอบเขตบนของy, mและd(เช่นอาจdจะเป็น 2147483000?)
ErikF

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

1
รูปแบบเอาต์พุตเกี่ยวกับอะไร เราสามารถส่งออกวัตถุวันที่ได้หรือไม่? เราสามารถนำวัตถุวันที่ได้หรือไม่?
Asone Tuhid

คำตอบ:


3

C (gcc) , 291 ไบต์

อันนี้สนุกมากที่ได้คืนค่าเดียวกันกับ 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]++;}

ลองออนไลน์!

ยกเลิกแข็งแรงเล่นกอล์ฟ:

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

$,=$";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เป็น OP คาดหวัง (กรณีทดสอบ 6)
sundar - Reinstate Monica

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) สำหรับค่าที่จะเพิ่ม

ผลลัพธ์มาพร้อมกับ prepended 12:00:00 GMTซึ่งเป็นรูปแบบเริ่มต้นISOdateของ


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

Bash , 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

PHP , 203 ไบต์

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

วิธีเรียกใช้:

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

ตัวอย่าง:

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

หรือลองออนไลน์!

การทดสอบ: ลองออนไลน์!


0

T-SQL, 53 ไบต์

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

ฉันไม่แน่ใจว่ามันสำคัญ แต่ฉันใช้การปรับปีตามด้วยการปรับเดือนตามด้วยวัน ตรวจสอบค่าทดสอบทั้งหมดแล้ว

ตามมาตรฐาน IO ของเราใส่จะนำมาจากตารางที่มีอยู่ก่อนทีมีวันฟิลด์และจำนวนเต็มเขตY , Mและd

สังเกตว่าน่าสนใจไม่ใช่ตัวพิมพ์ใหญ่ที่สำคัญระหว่างรหัสประเภทวันที่ ( D , MและY ) และค่าอินพุตของฉัน ( d , ม.และY ) เพียงคำสั่งของพารามิเตอร์ใน SQLDATEADDฟังก์ชั่น


1
กรณีทดสอบนี้ผ่าน 6 หรือไม่? เนื่องจากมันไม่ได้ใช้กฎข้อที่ 4 ฉันจึงคิดว่าจะให้2001 3 1แทน2001 2 28การป้อนข้อมูล 6
sundar - Reinstate Monica

@Sundar ดูเหมือนว่าคุณถูกต้อง ฉันคิดว่าฉันผ่านการทดสอบทั้งหมดแล้ว ฉันจะดูว่าจะสามารถคง ...
BradC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.