Temukan Tanggal terdekat, diberi TargetDate dan Hari Minggu

12

Temukan Tanggal terdekat ke TargetDate untuk Hari Minggu tertentu.

Misalnya, diberi tanggal 20161219dan satu hari dalam seminggu Friday (6), jawabannya adalah 20161216.

Contoh lain, diberi tanggal 20161219dan satu hari dalam seminggu Wednesday (4), jawabannya adalah 20161221.

Contoh terakhir, diberi tanggal 20161219dan hari dalam seminggu Monday (2), jawabannya adalah 20161219.

Aturan:

  • Format Tanggal untuk input dan output harus sesuai. Dalam contoh, saya menggunakan yyyymmdd, tetapi Anda dapat menggunakan format apa pun sepanjang tahun (setidaknya dua digit), bulan, dan hari dalam sebulan "dapat dibaca manusia".
  • Day of Week dimasukkan sebagai bilangan bulat. Dalam contoh saya, hari Minggu adalah hari pertama dalam seminggu, oleh karena itu itu adalah hari dalam jumlah minggu 1. Anda dapat memiliki penomoran Day of Week, selama Anda mencatatnya ketika berbeda dari contoh.
  • Tahun 1970 hingga 2030 harus diakomodasi.
  • Alat dan pustaka tanggal bahasa umum diizinkan, tetapi kredibilitas jalanan diberikan kepada mereka yang memilih untuk tidak menggunakannya.
  • Jumlah byte terkecil menang.
Brett VanderVeen
sumber
2
Bisakah jawaban mengambil tanggal dalam bentuk yang berbeda jika nyaman? Juga hari-hari dalam seminggu juga terlihat tidak nyaman untuk bahasa yang menjadikan hari Senin sebagai hari pertama dalam seminggu
Blue
4
Ya, persyaratan format yang ketat membuat tugas ini lebih banyak tentang parsing / mengubah / memformat, daripada tentang menemukan tanggal yang sebenarnya. Akankah IMO lebih baik untuk menentukannya di sepanjang baris " Anda dapat menerima tanggal dan hari kerja dalam format yang masuk akal, selama Anda menggunakan format yang sama untuk input dan output. ". Tetapi karena banyak orang telah mengirimkan jawaban, saya kira itu harus tetap seperti sekarang.
smls
@ smls Saya setuju. Pelajaran yang dipetik untuk waktu berikutnya.
Brett VanderVeen
1
@ BrettVanderVeen Saya tidak berpikir sudah terlambat untuk bersantai. Anda bisa menambahkan komentar ke masing-masing (saat ini 8) jawaban tentang spesifikasi yang diperbarui. Saya pernah melakukan itu pada kesempatan tertentu.
Adám

Jawaban:

1

Perl 6 , 46 byte

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

Sebuah lambda yang menerima dua argumen: String tanggal dalam yyyy-mm-ddformat, dan angka hari kerja antara 1= Senin dan 7= Minggu.

Penjelasan:

                           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.

Menggunakan format tanggal dan hari kerja yang digunakan dalam contoh, itu akan menjadi 88 byte:

{S:g/\-//with ~first *.day-of-week==($^b-2)%7+1,Date.new(|($^a~~/(....)(..)(..)/))-3..*}
seseorang
sumber
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
Brett VanderVeen
@ BrettVanderVeen: Diperbarui.
smls
2

Perl 6 , 83 byte

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

Cobalah

Diperluas

->     # 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 「-」
  }
}
Brad Gilbert b2gills
sumber
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
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)

Menggunakan %Y-%m-%dformat tanggal. Jika %a %b %d %Yformat tanggal dapat diterima, maka untuk 82 byte:

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

Saya bisa menyimpan 2 byte lebih lanjut dengan membutuhkan hari Minggu = 10 hingga Sabtu = 16, tapi itu hari yang konyol dalam pemetaan seminggu. Sebelumnya 142 141 byte (terima kasih kepada @Guedes) versi yang menggunakan format tanggal YYYYMMDD tertentu, dengan penjelasannya:

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

Ini terasa terlalu lama. Penjelasan: Pertama, masukkan -tanggal untuk memasukkannya ke dalam format ISO yang new Datekemudian dapat diuraikan. Kemudian, bandingkan hari yang diinginkan dengan hari yang sebenarnya untuk mendapatkan nilai antara -3dan 3untuk offset aktual. Keajaiban 9datang dari 7(karena %CPU modulo, bukan modulo benar) plus 3(untuk -3offset) minus 1(karena n1-diindeks dan getDay0-diindeks). Tanggal kemudian dikonversi kembali ke format ISO dan karakter yang tidak diinginkan dihapus.

Neil
sumber
Anda dapat menyimpan satu byte dengan mengganti ganti pertama ke.replace(/(?=..(..)?$)/g,'-')
Washington Guedes
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
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. repl.it

Fungsi tanpa nama yang mengambil string s, tanggal seperti yang ditentukan (menggunakan format string t='%Y%m%d'untuk input dan output) dan angka dalam [1,7] n,.
Memeriksa tujuh hari dari tiga hari sebelum tiga hari setelah itu diberikan untuk hari dalam seminggu yang diminta.
Minggu masuk datetimedimulai pada hari Senin dan berbasis nol, jadi tesnya adalah (n-2)%7==d.weekday().

Jonathan Allan
sumber
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
Brett VanderVeen
1

Bash + coreutils, 50

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

Cobalah online .

  • date -d$1 +%uberi hari dalam seminggu (1..7); 1 adalah Senin
  • Ini dikurangkan dari input hari dalam seminggu untuk memberikan perbedaan indeks hari. Kami ingin menambahkan faktor antara dalam rentang [-3, 3] ke tanggal input untuk mendapatkan tanggal terdekat, jadi kami menambahkan faktor ajaib 9, ambil modulo 7, lalu kurangi 3. Faktor ajaib 9 adalah 3 + 7 - 1. 3 menyesuaikan rentang input untuk rentang [-3, 3], dan dikurangi lagi setelah modulo. 7 diperlukan karena bash modulo sama dengan modulo CPU dan dapat memberikan -ve hasil - menambahkan 7 menyesuaikan ke kisaran yang tepat. -1 adalah karena dalam input, 1 adalah hari Minggu, tetapi dengan% u output, 1 adalah hari Senin.
  • Bagian luar datekemudian mem <input date> + <magic factor>days- parsing dan menyajikannya dalam format YYYYMMDD.
Trauma Digital
sumber
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
Brett VanderVeen
1

SAS Macro Language, 110 Bytes

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

Bahasa golf yang mengerikan tapi inilah penjelasannya (dari dalam ke luar):

Buat makro syang menerima input tanggal ddan hari kerja numerik a. Kemudian %eval(%sysfunc(putn(&d,8.))-4)mengonversi tanggal menjadi tanggal numerik SAS dan menguranginya 4 hari. The intnxfungsi kemudian kembali terjadinya berikutnya dari hari kerja yang ditentukan. putnkemudian memformat tanggal kembali ke yyyymmdd dan %putmencetak output ke log.

J_Lard
sumber
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
Brett VanderVeen
1

Mathematica, 85 49 byte

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

Format input untuk tanggal adalah daftar suka {2016, 12, 16}atau aktual DateObject(saya pikir beberapa yang lain juga berfungsi, tapi saya sudah menguji ini). Dalam kedua kasus, format output akan cocok secara otomatis. Penomoran hari dimulai 1pada hari Senin.

Idenya adalah untuk menghitung perbedaan antara input hari kerja dan hari kerja target dengan #2-#~DateValue~"ISOWeekDay"dan kemudian memetakannya [-3, 3]menggunakan modulo dengan offset (yaitu Mod[...,7,-3]). Hasilnya hanya ditambahkan ke tanggal input (unit default untuk penambahan objek tanggal adalah hari).

Martin Ender
sumber
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
Brett VanderVeen
@ BrettVanderVeen terima kasih, diedit.
Martin Ender
1

R, 119 77 56 byte

Fungsi tanpa nama yang mengambil dua input, tanggal D(string) dan hari d(numerik).

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

Menggunakan fungsi wday()dari lubridatepaket. Itu dapat dengan mudah mengkonversi Dateobjek menjadi hari kerja dengan 1diperlakukan sebagai hari Minggu secara default.

Sunting: I / O sekarang merupakan as.Date()fungsi default :"YYYY-mm-dd"

Tidak Dijelaskan dan Dijelaskan

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                                    
}

Sunting: Sekarang membuat urutan +-3hari di mana setiap hari kerja tertentu dijamin dapat ditemukan. Selanjutnya kita hanya perlu mencocokkan satu hari yang membuat masalah menjadi lebih mudah.

Billywob
sumber
FYI, saya mengurangi aturan format tanggal dan hari dalam seminggu. Jangan ragu untuk mengirim kembali.
Brett VanderVeen
@ BrettVanderVeen Terima kasih, diperbarui.
Billywob