给定目标日期和星期几,找到最近的日期


12

查找给定星期几中与TargetDate最接近的日期。

例如,给定日期20161219和星期几Friday (6),答案为20161216

另一个例子,给定日期20161219为星期几Wednesday (4),答案为20161221

最后一个例子,给定日期20161219为星期几Monday (2),答案为20161219

规则:

  • 输入和输出的日期格式必须匹配。在示例中,我使用yyyymmdd,但是您可以使用任何格式,只要年份(至少两位数),月份和月份中的“可读”即可。
  • 星期几以整数形式输入。在我的示例中,星期日是星期几,因此它是星期几1。您可以使用“星期几”中的任何编号,只要您在与示例不同的地方注明即可。
  • 必须容纳1970年到2030年。
  • 允许使用通用语言的日期工具和库,但对那些选择不使用它们的人则赋予了信誉。
  • 最少的字节数获胜。

2
如果方便的话,答案可以采用其他形式的日期吗?同样,对于那些将周一作为一周的第一天的语言,一周中的日子也很不方便
Blue

4
是的,严格的格式要求使此任务更多地涉及解析/转换/格式化,而不是实际的日期查找。IMO最好按照“ 您可以接受任何合理的格式接受日期和星期几,只要您对输入和输出使用相同的格式 ”来指定它。但是由于很多人已经提交了答案,所以我想必须保持现状。
smls

@smls我同意。下一次学习的教训。
布雷特·范德温

1
@BrettVanderVeen我认为放松要求不是为时已晚。您只需在有关更新的规范的每个(当前有8个)答案中添加评论。我有时会这样做。
2013年

Answers:


1

Perl 6,46个字节

{~first *.day-of-week==$^b,Date.new($^a)-3..*}

接受两个参数的lambda:yyyy-mm-dd格式为日期的字符串以及1= Monday和7= Sunday 之间的工作日数字。

说明:

                           Date.new($^a)       # Construct Date object from first argument.
                                        -3     # Subtract 3 days.
                                          ..*  # Construct a Range from that, to infinity.
  first                   ,                    # Iterate the range, and return first date...
        *.day-of-week==$^b                     # whose weekday number equals the second arg.

使用示例中使用的日期和星期几格式,将为88个字节:

{S:g/\-//with ~first *.day-of-week==($^b-2)%7+1,Date.new(|($^a~~/(....)(..)(..)/))-3..*}

仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

@BrettVanderVeen:已更新。
smls

2

Perl 6、83个字节

->$_,\w{~(Date.new(|m/(....)(..)(..)/)-3...*.day-of-week%7+1==w)[*-1]~~{S:g/"-"//}}

尝试一下

展开式

->     # pointy block lambda
  $_,
  \w
{
  ~(  # turn into a Str

    Date.new( |m/(....)(..)(..)/ ) - 3 # three days earlier
    ...                                # generate a sequence
    *.day-of-week % 7 + 1 == w         # stop when the right day is found

  )[*-1]  # the last one

  ~~      # apply the following block

  {
    S:g/"-"//  # remove 「-」
  }
}

仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

2

JavaScript(ES6),93个字节

(s,n,d=new Date(s))=>d.setDate(d.getDate()+(n+9-d.getDay())%7-3)&&d.toISOString().slice(0,10)

使用%Y-%m-%d日期格式。如果%a %b %d %Y是可接受的日期格式,则为82个字节:

(s,n,d=new Date(s))=>d.setDate(d.getDate()+(n+9-d.getDay())%7-3)&&d.toDateString()

我可以通过要求Sunday = 10到Saturday = 16来进一步节省2个字节,但这是一个愚蠢的星期映射。上一页142个 141字节(多亏@Guedes)所使用的特定YYYYMMDD日期格式,其解释版本:

(s,n,d=new Date(s.replace(/(?=..(..)?$)/g,'-')))=>d.setDate(d.getDate()+(n+9-d.getDay())%7-3)&&d.toISOString().replace(/-(..)-(..).*/,'$1$2')

感觉太久了。说明:首先,将-s插入日期以使其具有ISO格式,new Date然后可以对其进行解析。然后,将所需的日期与实际的日期进行比较,以获取介于-3和之间的值,3作为实际的偏移量。魔术9来自7(因为%是CPU模,而不是真正的模)加上3(对于-3偏移量)减去1(因为n是1索引,并且getDay是0索引)。然后将日期转换回ISO格式,并删除不需要的字符。


您可以保存一个字节,将第一个替换项更改为.replace(/(?=..(..)?$)/g,'-')
Washington Guedes

仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

1

Python,第150个 149字节

from datetime import*
lambda s,n,t='%Y%m%d':[d for d in[datetime.strptime(s,t)+timedelta(o-3)for o in range(7)]if(n-2)%7==d.weekday()][0].strftime(t)

149 ..

带有字符串s,指定日期(t='%Y%m%d'在输入和输出中均使用格式字符串)和[1,7]中的数字的未命名函数n
检查所要求的星期几中的前三天到后三天之间的七天。
的星期datetime从星期一开始,是从零开始的,因此测试是(n-2)%7==d.weekday()


仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

1

Bash + coreutils,50岁

date -d$1+$[($2-`date -d$1 +%u`+9)%7-3]day +%Y%m%d

在线尝试

  • date -d$1 +%u给出星期几(1..7); 1是星期一
  • 从输入的星期几中减去该值即可得出不同的日期索引。我们想要在输入日期的[-3,3]范围内添加一个因子以获得最接近的日期,因此我们添加了一个魔术因子9,取模7,然后减去3。魔术因子9是3 + 7 - 1。3调节输入范围为[-3,3],并在取模后再次减去。之所以需要7,是因为bash模与CPU模相同,并且可以给出-ve结果-加7将调整到正确的范围。-1是因为在输入中1是星期日,但是在%u输出中1是星期一。
  • 然后外部date解析<input date> + <magic factor>days并以YYYYMMDD格式呈现。

仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

1

SAS宏语言,110字节

%macro s(d,a);%put %sysfunc(putn(%sysfunc(intnx(week.&a.,%eval(%sysfunc(putn(&d,8.))-4),1)),yymmddn8.));%mend;

一种糟糕的高尔夫语言,但这是解释(从内而外):

创建一个s接受日期输入d和数字星期几的宏a。然后%eval(%sysfunc(putn(&d,8.))-4)将日期转换为SAS数字日期并将其减少4天。intnx然后该函数返回指定工作日的下一次出现。putn然后将日期格式化回yyyymmdd并将%put输出打印到日志。


仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

1

Mathematica,85个 49字节

#~DatePlus~Mod[#2-#~DateValue~"ISOWeekDay",7,-3]&

日期的输入格式可以是类似的列表,也可以是{2016, 12, 16}实际的DateObject(我认为其他一些格式也可以,但是我已经测试了这些格式)。无论哪种情况,输出格式都会自动匹配。天数从1星期一开始。

想法是使用计算出输入工作日与目标工作日之间的差#2-#~DateValue~"ISOWeekDay",然后[-3, 3]使用具有偏移量的模(即Mod[...,7,-3])将其映射到。将结果简单地添加到输入日期(添加日期对象的默认单位是天)。


仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

@BrettVanderVeen谢谢,编辑。
马丁·恩德

1

R,119 77 56字节

带有两个输入的未命名函数,日期D(字符串)和日期d(数字)。

function(D,d,s=-3:3+as.Date(D))s[lubridate::wday(s)==d]

使用函数wday()lubridate包。它可以方便地将Date对象转换为工作日,1默认情况下将其视为星期日。

编辑:I / O现在是该as.Date()功能的默认值:"YYYY-mm-dd"

脱胎换骨和解释

function(D,d){
    D=as.Date(D);            # Format input date
    s=-3:3+D;                # Generate sequence of +- 3 days
    s[lubridate::wday(s)==d] # Match the weekday that equals to target day                                    
}

编辑:现在创建一个+-3保证可以在其中找到给定工作日的天序列。随后,我们只需要匹配一天,这使问题变得更加容易。


仅供参考,我放宽了日期和星期几格式规则。随时重新提交。
布雷特·范德温

@BrettVanderVeen谢谢,已更新。
Billywob
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.