ค้นหาวันที่ใกล้ที่สุดที่กำหนด TargetDate และวันของสัปดาห์


12

ค้นหาวันที่ใกล้เคียงที่สุดกับ TargetDate ในวันที่กำหนด

ตัวอย่างเช่นกำหนดวันของ20161219และวันของสัปดาห์ของคำตอบคือFriday (6)20161216

อีกตัวอย่างหนึ่งที่กำหนดวันของ20161219และวันของสัปดาห์ของคำตอบคือWednesday (4)20161221

ตัวอย่างสุดท้ายกำหนดวันของ20161219และวันของสัปดาห์ของคำตอบคือMonday (2)20161219

กฎ:

  • รูปแบบวันที่สำหรับอินพุตและเอาต์พุตต้องตรงกัน ในตัวอย่างที่ฉันใช้yyyymmddแต่คุณสามารถใช้รูปแบบใดก็ได้ตราบใดที่ปี (อย่างน้อยสองหลัก) เดือนและวันของเดือนนั้นเป็น "มนุษย์สามารถอ่านได้"
  • Day of Week ป้อนข้อมูลเป็นจำนวนเต็ม 1ในตัวอย่างของฉันวันอาทิตย์เป็นวันแรกของสัปดาห์จึงจะเป็นวันของจำนวนสัปดาห์ คุณสามารถกำหนดวันในสัปดาห์ใดก็ได้ตราบใดที่คุณสังเกตว่ามันแตกต่างจากตัวอย่าง
  • ปี 1970 ถึง 2030 จะต้องมีที่พักอาศัย
  • อนุญาตให้ใช้เครื่องมือและไลบรารีของภาษาที่พบได้ทั่วไป แต่จะมีการมอบเครดิตถนนให้กับผู้ที่เลือกที่จะไม่ใช้
  • จำนวนไบต์ที่น้อยที่สุดจะชนะ

2
คำตอบสามารถใช้วันที่ในรูปแบบอื่นได้หรือไม่หากสะดวก? นอกจากนี้วันของสัปดาห์ก็ไม่สะดวกสำหรับภาษาที่ใช้วันจันทร์เป็นวันแรกของสัปดาห์
Blue

4
ใช่ความต้องการรูปแบบที่เข้มงวดทำให้งานนี้มากขึ้นเกี่ยวกับการแยก / การแปลง / การจัดรูปแบบมากกว่าเกี่ยวกับการค้นหาวันที่จริง จะมี IMO ดีกว่าที่จะระบุตามบรรทัดของ " คุณสามารถยอมรับวันที่และวันทำงานในรูปแบบที่สมเหตุสมผลใด ๆ ตราบใดที่คุณใช้รูปแบบเดียวกันสำหรับอินพุตและเอาต์พุต " แต่เนื่องจากผู้คนจำนวนมากได้ส่งคำตอบไปแล้วฉันคิดว่ามันต้องเป็นอย่างที่มันเป็นอยู่ตอนนี้
smls

@smls ฉันเห็นด้วย บทเรียนได้เรียนรู้ในครั้งต่อไป
Brett VanderVeen

1
@BrettVanderVeen ฉันไม่คิดว่ามันจะสายเกินไปที่จะผ่อนคลายความต้องการ คุณสามารถเพิ่มความคิดเห็นให้กับคำตอบ (ปัจจุบัน 8) แต่ละข้อเกี่ยวกับข้อมูลจำเพาะที่อัปเดต ฉันทำเช่นนี้ในบางโอกาส
อดัม

คำตอบ:


1

Perl 6 , 46 ไบต์

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

แลมบ์ดาที่ยอมรับสองข้อโต้แย้ง: สตริงวันที่ในyyyy-mm-ddรูปแบบและหมายเลขวันทำงานระหว่าง1= วันจันทร์และ7= วันอาทิตย์

คำอธิบาย:

                           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..*}

FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

@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 「-」
  }
}

FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

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

ฉันสามารถบันทึกเพิ่มอีก 2 ไบต์โดยกำหนดให้วันอาทิตย์ = 10 ถึงวันเสาร์ = 16 แต่นั่นเป็นวันที่น่าเบื่อของการทำแผนที่สัปดาห์ ก่อนหน้า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 modulo ไม่ใช่ modulo จริง) บวก3(สำหรับ-3offset) ลบ1(เพราะnมีการจัดทำดัชนี 1 และgetDayเป็น 0-indexed) จากนั้นวันที่จะถูกแปลงกลับเป็นรูปแบบ ISO และลบอักขระที่ไม่ต้องการออก


คุณสามารถบันทึกหนึ่งไบต์เปลี่ยนการแทนที่แรกเป็น.replace(/(?=..(..)?$)/g,'-')
Washington Guedes

FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

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)

Oouuf, 149. repl.it

ฟังก์ชั่นที่ไม่มีชื่อที่ใช้สตริงsวันตามที่กำหนด (โดยใช้รูปแบบของสตริงt='%Y%m%d'สำหรับทั้ง input และ output) และตัวเลขใน n[1,7]
ตรวจสอบเจ็ดวันจากสามวันก่อนหน้าสามวันหลังจากนั้นให้สำหรับวันของสัปดาห์ที่ร้องขอ
สัปดาห์ในการเริ่มต้นในวันจันทร์และจะขึ้นอยู่กับศูนย์เพื่อการทดสอบdatetime(n-2)%7==d.weekday()


FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

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 modulo เหมือนกับ CPU modulo และสามารถให้ผลลัพธ์แบบ -ve - เพิ่ม 7 ปรับให้อยู่ในช่วงที่เหมาะสม -1 เป็นเพราะในอินพุต 1 คือวันอาทิตย์ แต่มีเอาต์พุต% u เป็น 1 คือวันจันทร์
  • ด้านนอกdateแล้วแยกวิเคราะห์<input date> + <magic factor>daysและนำเสนอในรูปแบบ YYYYMMDD

FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

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พิมพ์ผลลัพธ์ไปยังบันทึก


FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

1

Mathematica, 85 49 ไบต์

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

รูปแบบการป้อนข้อมูลสำหรับวันที่อาจเป็นรายการที่เหมือน{2016, 12, 16}หรือเป็นของจริงDateObject(ฉันคิดว่าบางคนทำงานได้ดี แต่ฉันได้ทดสอบสิ่งเหล่านี้แล้ว) ไม่ว่าในกรณีใดรูปแบบเอาต์พุตจะจับคู่โดยอัตโนมัติ การนับวันเริ่มจาก1วันจันทร์

แนวคิดคือการคำนวณความแตกต่างระหว่างอินพุตวันทำงานและวันทำงานเป้าหมายด้วย#2-#~DateValue~"ISOWeekDay"จากนั้นทำแผนที่[-3, 3]โดยใช้โมดูโลที่มีออฟเซ็ต (เช่นMod[...,7,-3]) ผลลัพธ์จะถูกเพิ่มเข้าในวันที่ป้อนข้อมูล (หน่วยเริ่มต้นสำหรับการเพิ่มวัตถุวันที่คือวัน)


FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

@BrettVanderVeen ขอบคุณแก้ไขแล้ว
Martin Ender

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"

Ungolfed และอธิบาย

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วันที่รับประกันวันทำงานใด ๆ ที่กำหนดให้หลังจากนั้นเราจะต้องจับคู่หนึ่งวันเท่านั้นซึ่งทำให้ปัญหาง่ายขึ้นมาก


FYI ฉันผ่อนคลายกฎการจัดรูปแบบวันที่และวันในสัปดาห์ รู้สึกฟรีเพื่อส่งอีกครั้ง
Brett VanderVeen

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