Знайдіть найближчу дату із зазначенням цільової дати та дня тижня


12

Знайдіть найближчу дату до TargetDate для певного дня тижня.

Наприклад, з урахуванням дати 20161219та дня тижня Friday (6)відповідь є 20161216.

Інший приклад, з урахуванням дати 20161219та дня тижня Wednesday (4), відповідь є 20161221.

Остаточний приклад, з урахуванням дати 20161219та дня тижня Monday (2), відповідь є 20161219.

Правила:

  • Формат дати для введення та виведення повинен відповідати. У прикладах я використовував yyyymmdd, але ви можете використовувати будь-який формат, якщо рік (принаймні дві цифри), місяць та день місяця "читаються людиною".
  • День тижня вводиться як ціле число. У моєму прикладі неділя є першим днем ​​тижня, тому це число тижня 1. Ви можете мати будь-яку нумерацію Дня тижня, якщо ви відзначите її, коли вона відрізняється від прикладу.
  • 1970-12030 роки повинні бути розміщені.
  • Дозволяються загальні мовні дати та бібліотеки, але вуличні кредити надаються тим, хто вирішив не використовувати їх.
  • Найменша кількість байтів виграє.

2
Чи можуть відповіді прийняти дату в іншій формі, якщо зручно? Також дні тижня також сприймають незручності для мов, які вважають понеділок першим днем ​​тижня
Синій

4
Так, суворі вимоги до формату роблять це завдання скоріше щодо розбору / перетворення / форматування, ніж про фактичне знаходження дати. ІМО було б краще вказати його відповідно до пункту " Ви можете приймати дату та будній день у будь-якому розумному форматі, якщо ви використовуєте той самий формат для введення та виведення даних. " Але оскільки купа людей вже надіслала відповіді, я думаю, що це потрібно тримати так, як зараз.
smls

@smls Я згоден. Урок дізнався наступного разу.
Бретт ВандерВін

1
@BrettVanderVeen Я не думаю, що це занадто пізно, щоб послабити вимоги. Ви можете просто додати коментар до кожної з (зараз 8) відповідей щодо оновлених специфікацій. Я робив таке з нагоди.
Adám

Відповіді:


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, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

@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, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

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(тому що %це модуль процесора, а не справжній модуль) плюс 3(для -3зміщення) мінус 1(тому що n1-індексований і getDay0-індексований). Дату потім перетворюють назад у формат ISO, а небажані символи видаляють.


Ви можете зберегти один байт, змінивши першу заміну на.replace(/(?=..(..)?$)/g,'-')
Вашингтон Гедес

FYI, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

1

Пітон, 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. відп

Без імені функція , яка приймає рядок s, дату , як зазначено ( з використанням формату рядка t='%Y%m%d'для введення і виведення) і число в [1,7], n.
Перевіряє сім днів від трьох днів до трьох днів після цього, вказаних для запитуваного дня тижня.
Тиждень datetimeпочинається з понеділка і базується на нулі, тому тест є (n-2)%7==d.weekday().


FYI, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

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 такий же, як і модуль процесора, і може дати результат -ve - додавши 7 коригує в потрібний діапазон. -1 тому, що на вході 1 - неділя, але при випуску% u - 1 - понеділок.
  • Зовнішня dateчастина потім розбирає <input date> + <magic factor>daysта представляє її у форматі РРРРММДД.

FYI, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

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, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

1

Математика, 85 49 байт

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

Формат введення для дат є або списком подобається, {2016, 12, 16}або фактичним DateObject(я думаю, що деякі інші також працюють, але я перевірив їх). У будь-якому випадку формат виводу буде відповідати автоматично. Нумерація днів починається з 1понеділка.

Ідея полягає в тому, щоб обчислити різницю між вхідним будним днем ​​і цільовим будним днем, #2-#~DateValue~"ISOWeekDay"а потім зіставити його [-3, 3]за допомогою модуля зі зміщенням (тобто Mod[...,7,-3]). Результат просто додається до дати введення (одиниця за замовчуванням для додавання об'єкта дати - дні).


FYI, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

@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, а за замовчуванням трактується як неділя.

Редагувати: тепер введення / виведення за замовчуванням 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днів, за які гарантовано знайдеться будь-який будній день. Згодом нам потрібно лише зіставити один день, що значно полегшило проблему.


FYI, я зменшив правила дати та дня тижня. Сміливо відправте повторно.
Бретт ВандерВін

@BrettVanderVeen Дякую, оновлено.
Billywob
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.