日期发生


9

给定三个非负整数ym和,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

years年(除以4的年份,除非不能除以400的整数,否则不能除以100)必须适当处理。所有输入和输出将在您语言的可表示整数范围内。

测试用例

测试用例以格式提供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进行测试。

这是 ,因此以最短的解决方案(每种语言)为准。


沙盒帖子(已删除)
Mego,

2
@LuisfelipeDejesusMunoz输入格式并不重要,PPCG上的规范也不重要。
Mego

是否有任何限制的上限ym以及d(如可能d是2147483000?)
ErikF

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

1
输出格式呢?我们可以输出日期对象吗?我们可以带日期对象吗?
Asone Tuhid

Answers:


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 28OP期望的(测试用例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


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

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标准,输入是从预先存在的表t中获取的,表t中包含日期字段a和整数字段ymd

有趣的是,日期类型代码DMY)和我的输入值dmy)之间的大写无关紧要,只是SQL DATEADD函数中参数的顺序。


1
该测试案例6通过了吗?因为它没有实现第4条,我认为它会放弃2001 3 1,而不是2001 2 28输入6
孙大信-恢复莫妮卡

@sundar看起来您是正确的;我以为我已经通过了所有测试用例。我看看是否可以解决...
BradC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.