Tìm ngày gần nhất, được đưa ra một TargetDate và ngày trong tuần


12

Tìm ngày gần nhất với TargetDate cho một ngày trong tuần nhất định.

Ví dụ, đưa ra một ngày 20161219và một ngày trong tuần Friday (6), câu trả lời là 20161216.

Một ví dụ khác, đưa ra một ngày 20161219và một ngày trong tuần Wednesday (4), câu trả lời là 20161221.

Một ví dụ cuối cùng, đưa ra một ngày 20161219và một ngày trong tuần Monday (2), câu trả lời là 20161219.

Quy tắc:

  • Định dạng ngày cho đầu vào và đầu ra phải khớp. Trong các ví dụ, tôi đã sử dụng yyyymmdd, nhưng bạn có thể sử dụng bất kỳ định dạng nào miễn là năm (ít nhất hai chữ số), tháng và ngày trong tháng là "con người có thể đọc được".
  • Ngày trong tuần là đầu vào dưới dạng số nguyên. Trong ví dụ của tôi, Chủ nhật là ngày đầu tuần, do đó là ngày trong tuần 1. Bạn có thể có bất kỳ đánh số Ngày nào trong tuần, miễn là bạn ghi chú nó khi nó khác với ví dụ.
  • Năm 1970 đến 2030 phải được cung cấp.
  • Các công cụ và thư viện ngày ngôn ngữ thông thường được cho phép, nhưng tín dụng đường phố được trao cho những người chọn không sử dụng chúng.
  • Số byte ít nhất sẽ thắng.

2
Câu trả lời có thể mất ngày ở một hình thức khác nếu thuận tiện? Ngoài ra, các ngày trong tuần cũng thấy bất tiện cho các ngôn ngữ lấy ngày thứ Hai là ngày đầu tuần
Blue

4
Vâng, các yêu cầu định dạng nghiêm ngặt làm cho nhiệm vụ này nhiều hơn về phân tích / chuyển đổi / định dạng, hơn là về việc tìm kiếm ngày thực tế. IMO sẽ tốt hơn nếu chỉ định nó dọc theo dòng " Bạn có thể chấp nhận ngày và ngày trong tuần ở bất kỳ định dạng hợp lý nào, miễn là bạn sử dụng cùng định dạng cho đầu vào và đầu ra. ". Nhưng vì một loạt người đã gửi câu trả lời, tôi đoán nó phải được giữ nguyên như bây giờ.
smls

@smls tôi đồng ý. Bài học kinh nghiệm cho lần sau.
Brett VanderVeen

1
@BrettVanderVeen Tôi không nghĩ đã quá muộn để thư giãn các yêu cầu. Bạn chỉ có thể thêm một nhận xét cho mỗi câu trả lời (hiện tại 8) về thông số kỹ thuật được cập nhật. Tôi đã làm như vậy nhân dịp.
Adám

Câu trả lời:


1

Perl 6 , 46 byte

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

Một lambda chấp nhận hai đối số: Chuỗi ngày có yyyy-mm-ddđịnh dạng và số ngày trong tuần giữa 1= Thứ Hai và 7= Chủ Nhật.

Giải trình:

                           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.

Sử dụng định dạng ngày và ngày trong tuần được sử dụng trong các ví dụ, nó sẽ là 88 byte:

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

FYI, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

@BrettVanderVeen: Đã cập nhật.
smls

2

Perl 6 , 83 byte

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

Thử nó

Mở rộng

->     # 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, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

2

JavaScript (ES6), 93 byte

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

Sử dụng %Y-%m-%dđịnh dạng ngày. Nếu %a %b %d %Ylà định dạng ngày có thể chấp nhận, thì với 82 byte:

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

Tôi có thể tiết kiệm thêm 2 byte bằng cách yêu cầu Chủ nhật = 10 đến Thứ bảy = 16, nhưng đó là một ngày lập bản đồ trong tuần ngớ ngẩn. Phiên bản 142 141 byte trước đó (nhờ @Guedes) đã sử dụng định dạng ngày YYYYMMDD cụ thể, với lời giải thích:

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

Điều này cảm thấy quá dài. Giải thích: Đầu tiên, chèn -s vào ngày để đưa nó vào định dạng ISO, new Datesau đó có thể phân tích cú pháp. Sau đó, so sánh ngày mong muốn với ngày thực tế để có giá trị giữa -33cho phần bù thực tế. Phép thuật 9xuất phát từ 7(vì %là modulo CPU, không phải là modulo thật) cộng với 3(cho phần -3bù) trừ 1(vì nđược lập chỉ mục 1 và được lập chỉ mục getDay0). Ngày sau đó được chuyển đổi lại thành định dạng ISO và loại bỏ các ký tự không mong muốn.


Bạn có thể lưu một byte thay đổi thay thế đầu tiên thành.replace(/(?=..(..)?$)/g,'-')
Washington Guedes

FYI, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

1

Python, 150 149 byte

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. thay thế

Hàm không tên có một chuỗi s, ngày như được chỉ định (sử dụng chuỗi định dạng t='%Y%m%d'cho cả đầu vào và đầu ra) và một số trong [1,7] , n.
Kiểm tra bảy ngày từ ba ngày trước ba ngày sau đó được đưa ra cho ngày trong tuần được yêu cầu.
Tuần datetimebắt đầu vào thứ Hai và không dựa trên, vì vậy bài kiểm tra là (n-2)%7==d.weekday().


FYI, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

1

Bash + coreutils, 50

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

Hãy thử trực tuyến .

  • date -d$1 +%uđưa ra ngày trong tuần (1..7); 1 là thứ hai
  • Điều này được trừ vào ngày đầu vào trong tuần để đưa ra sự khác biệt về chỉ số ngày. Chúng tôi muốn thêm một yếu tố trong phạm vi [-3, 3] vào ngày đầu vào để có ngày gần nhất, vì vậy chúng tôi thêm yếu tố ma thuật 9, lấy modulo 7, sau đó trừ 3. Yếu tố ma thuật 9 là 3 + 7 - 1. Cả 3 điều chỉnh phạm vi đầu vào cho phạm vi [-3, 3] và được trừ lại sau modulo. 7 là bắt buộc vì bash modulo giống như modulo CPU và có thể cho kết quả -ve - thêm 7 điều chỉnh vào phạm vi phù hợp. -1 là bởi vì trong đầu vào, 1 là Chủ nhật, nhưng với đầu ra% u, 1 là Thứ hai.
  • Bên ngoài datesau đó phân tích cú pháp<input date> + <magic factor>days và trình bày nó ở định dạng YYYYMMDD.

FYI, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

1

Ngôn ngữ vĩ mô SAS, 110 byte

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

Một ngôn ngữ chơi golf khủng khiếp nhưng đây là lời giải thích (từ trong ra ngoài):

Tạo một macro schấp nhận đầu vào ngày dvà một ngày trong tuần số a. Sau đó %eval(%sysfunc(putn(&d,8.))-4)chuyển đổi ngày thành ngày số SAS và giảm ngày 4 ngày. Các intnxchức năng sau đó trả về sự xuất hiện tiếp theo của các ngày trong tuần theo quy định. putnsau đó định dạng ngày trở lại yyyymmdd và %putin kết quả đầu ra vào nhật ký.


FYI, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

1

Toán học, 85 49 byte

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

Định dạng đầu vào cho ngày là một danh sách giống {2016, 12, 16}hoặc thực tế DateObject(tôi nghĩ rằng một vài người khác cũng hoạt động, nhưng tôi đã thử nghiệm những điều này). Trong cả hai trường hợp, định dạng đầu ra sẽ tự động khớp. Việc đánh số ngày bắt đầu từ 1thứ Hai.

Ý tưởng là để tính toán sự khác biệt giữa ngày trong tuần đầu vào và ngày trong tuần mục tiêu với #2-#~DateValue~"ISOWeekDay"và sau đó ánh xạ nó thành [-3, 3]sử dụng một modulo có offset (nghĩa là Mod[...,7,-3]). Kết quả chỉ được thêm vào ngày đầu vào (đơn vị mặc định để thêm đối tượng ngày là ngày).


FYI, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

@BrettVanderVeen cảm ơn, chỉnh sửa.
Martin Ender

1

R, 119 77 56 byte

Hàm không tên có hai đầu vào, ngày D(chuỗi) và ngày d(số).

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

Sử dụng chức năng wday()từ lubridategói. Nó có thể thuận tiện chuyển đổi Datecác đối tượng thành các ngày trong tuần với1 được coi là Chủ nhật theo mặc định.

Chỉnh sửa: I / O hiện là mặc định của as.Date()chức năng:"YYYY-mm-dd"

Ung dung và giải thích

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                                    
}

Chỉnh sửa: Bây giờ tạo một chuỗi +-3ngày mà bất kỳ ngày nào trong tuần được đảm bảo sẽ được tìm thấy. Sau đó, chúng tôi chỉ phải khớp một ngày khiến vấn đề trở nên dễ dàng hơn nhiều.


FYI, tôi đã giảm bớt các quy tắc định dạng ngày và ngày trong tuần. Hãy gửi lại.
Brett VanderVeen

@BrettVanderVeen Cảm ơn, đã cập nhật.
Billywob
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.