Получить дату n-го дня недели в данном году и месяце


17

Вступление

Часто люди называют даты «второй пятницей августа 2018 года» или «четвертым воскресеньем марта 2012 года». Но трудно сказать, что это за дата! Ваша задача состоит в том, чтобы написать программу, которая получает год, месяц, день недели и целое число, и выводит эту дату.

Вызов

  • Для ввода вы получите год, месяц, день недели и число.

  • Вы можете вводить данные в любом приемлемом формате, например, использовать строку для дня недели или использовать нулевой индексированный день недели, или даже взять год и месяц в одной строке. Объясните свой входной формат в своем ответе.

  • Целое число, указывающее, какой день недели в месяце для таргетинга будет целым числом от 1 до 5. Целое число никогда не будет указывать на день недели, который не существует (например, пятую пятницу февраля 2019 года, который не существует).

  • Годы всегда будут положительными.

  • Ваш вывод может быть в любом разумном формате, включая печать вашей окончательной даты. Однако, пожалуйста, объясните ваш выходной формат и ответ.

  • Указание года и месяца в выходных данных необязательно. Кроме того, вы можете предположить, что дата действительна.

Пример ввода и вывода

Рассмотрим эти входные данные с форматом, принимающим год как четырехзначное число, месяц как целое число, день недели как строку и порядковый номер как целое число:

2019, 3, суббота, 2
2019, 12, воскресенье, 1
2019, 9 суббота, 1

Выход:

9 марта
1 декабря
7 сентября

Это , поэтому выигрывает самый короткий ответ.


1
Я думал, что смогу использовать GNU date, но забавно, у парсера есть ... интересная интерпретация здесь.
Дверная ручка

Может ли номер недели быть проиндексирован?
Джо Кинг,

Конечно, если это подходит вашей программе
Embodiment of Ignorance

Предлагаемый тестовый случай: 2018, 12, воскресенье 1
Адам

Предлагаемый тестовый пример: первая суббота сентября 2019 года
Shaggy

Ответы:


4

Шаблон MediaWiki, 19 байт

{{#time:r|{{{1}}}}}

Это порт ParserFunctions шаблона MediaWiki для этого ответа PHP

Примечание: #timeиспользуйте PHP strtotimeвнутри.


Пример ввода

{{#time: r | вторая суббота марта 2019 г.}}

Пример вывода

Сб, 09 марта 2019 00:00:00 +0000


3

Japt 19 15 байт

Входные данные: год, основанный на 0 индекс месяца, основанный на 0 индекс дня недели ( 0воскресенье) & n.

_XµW¶Ze}f@ÐUVYÄ

Попытайся

                    :Implicit input of U=year, V=month, W=weekday & X=n
       }f           :Output the first element generated by the right function that returns
                    : falsey (0) when passed through the left function
         @          :Right function. Y=0-based index of current iteration
          ÐUVYÄ     :  new Date(U,V,Y+1)
_                   :Left function. Z=date being passed
 Xµ                 :  Decrement X by
   W¶               :   Test W for equality with
     Ze             :    Z.getDay()

2

C # (интерактивный компилятор Visual C #) , 59 байт

(y,m,d,w)=>1+(d-(int)new DateTime(y,m,1).DayOfWeek+7)%7+7*w

Попробуйте онлайн!

-27 байт благодаря @EmbodimentOfIgnorance!

Меньше гольф-кода ...

// y: year
// m: month
// d: day of week (0 is Sunday)
// w: week number (0 based)
(y,m,d,w)=>
  // start on the first day of the month
  1+
  // determine the number of days to
  // the first occurrence of the
  // requested weekday
  (d-(int)new DateTime(y,m,1).DayOfWeek+7)%7+
  // add the number of requested weeks
  7*w

Возвращаемое значение является целым числом для дня месяца запрошенной даты.


Если вы
Embodiment of Ignorance

Еще раз спасибо за совет - (сегодня это дважды;) Я обновлю свои ответы.
Dana

2

SmileBASIC, 58 51 48 46 45 байт

READ N,M$DTREAD M$OUT,,D,W?(5-W+D*2)MOD 7+N*7

Ввод в форме: week,year/month/weekday

  • week: номер недели, 0 проиндексирован
  • year: год, 4 цифры
  • month: месяц (с 1 индексом), 2 цифры с 0добавлением
  • weekday: день недели (1-индексированный, 1 = воскресенье), 2 цифры с 0добавлением

Выходными данными является день месяца, индексированный 0.
Вторая суббота марта 2019 года будет 1,2019/03/078(9 марта)

Ungolfed

READ WEEK,M$
DTREAD M$ OUT ,,D,W
'Functions in SB can output multiple values using OUT.
'In this case, we don't need the first 2 values, so no variables are given.

PRINT (5-W+ D*2) MOD 7 +WEEK*7

объяснение

Форма ввода была специально выбрана так, чтобы год / месяц / день недели можно было передавать напрямую DTREAD, что представляет собой функцию, которая анализирует YYYY/MM/DDстроку и возвращает год / месяц / день в виде чисел, а также вычисляет день недели.

Однако обратите внимание, что там, где DTREADожидается день месяца, вместо этого мы указываем день недели. Это усложняет ситуацию, но также означает, что входных значений меньше, и нам не нужно добавлять /01в конец строки даты.

DTREADвыходы Wи D.
Wбудний день и Dдень недели в Wдень месяца.
(Таким образом, если вы введете 7в качестве дня недели, Dбудет 7и Wбудет любой день недели, 7-й день месяца)

Выражение (5-W+D*2)MOD 7используется для получения 1-го вхождения входного дня недели в виде 0-индексированного дня месяца. (Я понял это в основном методом проб и ошибок)

После этого программа просто добавляет WEEK*7.


Я действительно хотел бы, чтобы были отдельные слова для «дня недели» и «дня месяца».


2

Perl 6 , 52 48 байт

{1+($^c+4-Date.new($^a,$^b,1).daycount)%7+$^d*7}

Попробуйте онлайн!

Блок анонимного кода, который принимает данные в виде года, месяца, дня недели (воскресенье - 0) и номера недели (индексируется 0). Вывод является объектом даты.

Старое объяснение:

{                                                  } # Anonymous code block
 (   Date.new(         ))   # Create a new date with
              $^a,$^b,1     # With year, month and the first day
  $_=                       # Save in the variable $_
                         +  # Add to this
                           $^c+4                     # The given day plus 4
                          (     -.daycount)          # The number of days since 17 Nov, 1858
                                           %7        # Modulo 7 to get the correct day
                                             +$^d*7  # Plus the 7 times the number of weeks

Я думаю, что номер недели должен быть 1 проиндексирован
12Me21

@ 12Me21 Вопрос говорит о том, что ввод гибкий, но я спросил, будем ли мы брать номер недели с индексом 0
Джо Кинг

Это не похоже на другие месяцы. Я думаю, что вам нужно $^c+4-$!.daycount.
nwellnhof

@nwellnhof Ах, я должен был подумать об этом вместо проб и ошибок, смеется. Должно быть исправлено сейчас
Джо Кинг

1

MATL , 28 27 байт

'1 'ihYO31:q+t8XOi=!A)i)1XO

Это использует три входа:

  • Строка с месяцем и годом: 'March 2019'
  • Строка с тремя буквами, первая заглавная, обозначающая день недели: ' Sat'
  • Номер: 2.

Выход представляет собой строку день, год и месяц разделенных тире: 09-Mar-2019.

Попробуйте онлайн!

объяснение

Рассмотрим входы 'March 2019', 'Sat', 2.

'1 '    % Push this string
        % STACK: '1 '
ih      % Input string: month and year. Concatenate
        % STACK: '1 March 2019'
YO      % Convert to serial date number
        % STACK: 737485
31:q+   % Create vector [0 1 2 ... 30] and add element-wise
        % STACK: [737485 737486 737487 ... 737515]
t8XO    % Duplicate. Convert to date format 'ddd': day of week in three letters. Gives
        % a 2D char array
        % STACK: [737485 737486 737487 ... 737515], ['Fri'; 'Sat'; 'Sun'; ...; 'Sun']
i=      % Input string: day of week in three letters. Compare element-wise with broadcast
        % STACK: [737485 737486 737487 ... 737515],
        % [0 0 0; 0 0 0; ...; 1 1 1; 0 0 0; ... 1 1 1; ...]
!A      % True for rows containing only 1
        % STACK: [737485 737486 737487 ... 737515], [0 0 ... 1 ... 0 ... 1 ...]
)       % Index: uses the second vector as a mask into the first
        % STACK: [737486 737493 737500 737507 737514]
i)      % Input number. Index
        % STACK: 737493
1XO     % Convert to date format 'dd-mmm-yyyy'. Implicit display
        % STACK: '09-Mar-2019'

1

Python 3 , 92 82 байта

82 байта благодаря @Jo King

lambda y,m,d,w:z(y,m)[w-(z(y,m)[0][d]>0)][d]
from calendar import*
z=monthcalendar

Попробуйте онлайн!

Оригинальная версия, 92 байта

from calendar import*
def f(y,m,d,w):
 x=monthcalendar(y,m)
 if x[0][d]:w-=1
 return x[w][d]

Попробуйте онлайн!

Принимает год как целое число, месяц как целое число с 1 индексом, день недели как целое число с 0 индексами, где понедельник 0и воскресенье 6, а неделя месяца как целое число с 1 индексом.

Как это устроено:

# import monthcalendar
from calendar import*
# function with 4 inputs
def f(y,m,d,w):
 # get a 2-D array representing the specified month
 # each week is represented by an array
 # and the value of each element is its date of the month
 # Monday is the 0th element of each week, Sunday is the 6th element
 # days of the first week of the month before the 1st are 0s 
 x=monthcalendar(y,m)
 # if the first week of the month includes the desired day of week
 # convert the week of month to 0-index so that it takes into account the first week
 if x[0][d]:w-=1
 # return the weekday of the week number specified
 return x[w][d]

1

R , 72 69 байт

function(y,m,d,n,D=as.Date(paste0(y,-m,-1))+0:31)D[weekdays(D)==d][n]

Попробуйте онлайн!

Принимая вход как:

  • Номер года
  • Номер месяца (1-12)
  • Строка дня недели в текущей локали (TIO требует английского названия с заглавной буквой)
  • Порядковый номер (1-индексированный)

0

PHP , 46 , 43 , 31 байт

<?=date(d,strtotime($argv[1]));

Попробуйте онлайн!

Программа получает в качестве входных данных строку типа "second saturday of March 2019"

Программа печатает номер дня.

-12 байт благодаря Шегги.



Кроме того, я не думаю, что вам нужно ofво входных данных.
Лохматый

@ Шэгги, я думаю, это детали. Там может быть много вариантов.
Кирилл Малышев



0

Красный , 64 60 байт

func[y m d n][a: to-date[1 m y]d - a/10 - 7 % 7 +(n * 7)+ a]

Попробуйте онлайн!

Принимает год, месяц и день недели в виде цифр с индексом 1, понедельник - первый день недели.


да, to-dateэто вещь. может быть, это было бы полезно в соревновании по формату накануне Рождества
только для ASCII

@ ASCII-only Мы использовали nowдля этого вызова
Гален Иванов

1
да, но я думал об альтернативных методах (а именно, о " Eve"методе <repeat date2-date1 times> iirc)
только ASCII

@ Только для ASCII>> 25-Dec-2019 - 1-1-2019 == 358
Гален Иванов

0

APL (Dyalog Unicode) , 36 байт SBCS

Полная программа. Запрашивает для [year,month](январь 1), затем для дня (воскресенье 0), затем для n (сначала 1).

date⎕⊃d/⍨⎕=7|d←(⍳31)+days⎕⊣⎕CY'dfns'

Попробуйте онлайн!

⎕CY'dfns'с о р у в dfns библиотеке

 отменить результат этого в пользу ...

 подскажите консоль для [year,month]номеров

days[с]  дней [п] , поскольку 1899-12-31 от 0 - го числа этого месяца

(⍳31)+ добавить я ntegers 1 ... 31 в том , что

d← хранить в d(для д чисел ау)

7| остаток от деления на 7 (день недели с воскресеньем в 0 из-за хорошей эпохи)

⎕= подскажите консоль для номера дня недели и получите маску, где равны номера дня недели

d/⍨ фильтр d с этой маской

⎕⊃ подскажите консоль и используйте ее, чтобы выбрать из списка номеров дня

date[С]  метка даты и времени [n] (имеет завершающие нули для часов, минут, секунд, миллисекунд)


Нажмите [c] для кода и [n] для заметок.


0

JavaScript (ES6), 49 48 байт

f=
(a,d,n)=>(d+6-new Date(...a,7).getDay())%7+n*7-6
<div oninput=o.textContent=f([+y.value,+m.value],+d.value,+n.value)>Year: <input id=y type=number value=2019><br>Month: <select id=m><option value=0>Jan<option value=1>Feb<option value=2>Mar<option value=3>Apr<option value=4>May<option value=5>Jun<option value=6>Jul<option value=7>Aug<option value=8>Sep<option value=9>Oct<option value=10>Nov<option value=11>Dec</select><br>Day: <select id=d><option value=0>Sun<option value=1>Mon<option value=2>Tue<option value=3>Wed<option value=4>Thu<option value=5>Fri<option value=6>Sat</select><br>Count: <input id=n type=number value=1 min=1 max=5><pre id=o>

Принимает параметры как f([year, month], day, number). Месяц и день недели (начиная с воскресенья) индексируются нулем. Редактировать: 1 байт благодаря @Shaggy.


Является ли день недели в формате воскресенье-суббота или понедельник-воскресенье?
Воплощение Невежества

@EmbodimentofIgnorance Извините, я знал, что что-то забыл. (Фрагмент теперь использует select, чтобы упростить его.)
Neil

@EmbodimentofIgnorance, воскресенье 0в JS.
Лохматый

Ой. Я этого не знал, я не очень знаком с Javascript.
Воплощение Невежества


0

TSQL, 106 байт

DECLARE @ datetime='2019',@m int=3,@w char(2)='saturday',@p int=2

SELECT dateadd(wk,datediff(d,x,dateadd(m,@m-1,@)-1)/7,x)+@p*7FROM(SELECT
charindex(@w,' tuwethfrsasu')/2x)x

Выход:

2019-03-09 00:00:00.000

Попробуйте это


0

Котлин , 131 84 байта

47 байтов благодаря ASCII-только коду и комментарию.

Ввод: год, месяц, номер недели, номер недели, номер недели

Все целые числа от 1 до максимума в одной строке. Номер дня недели - воскресенье с 1 по субботу 7. Основная программа заставляет год терять 1900 для класса Дата, а месяц и день недели сдвигаются, чтобы начинаться с нуля вместо единицы перед вызовом лямбды. Вы можете ввести свои аргументы в текстовое поле ввода, чтобы попробовать свои собственные даты.

Выход: экземпляр класса Date. Основная программа отображает результат как: Сб. 09 марта 00:00:00 UTC 2019.

Существует расширенная версия с комментариями, объясняющими код для желающих узнать больше.

{y,m,d,w->val r=java.util.Date(y,m,7*w)
r.setDate(r.getDate()-(r.getDay()+7-d)%7)
r}

Попробуйте онлайн!


1
74 - использует тот же метод, что и ответы Scala и Groovy
только для ASCII


1
Больше нет необходимости в команде импорта, так что это не проблема: P
Только для ASCII
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.