Как использовать команду date, чтобы узнать, какой будет дата «понедельник, неделя 40»?


11

Как я могу использовать команду date, чтобы преобразовать что-то вроде «понедельника недели 40» в дату ISO?

Я играю с чем-то вроде этого:

date --date='monday week 40' +'%Y-%m-%d'

И дата, которую я ищу, будет 2011-10-03.

Но моя проблема в том, что эта строка даты недопустима, поэтому мне нужен другой подход для решения этой проблемы.

/Спасибо


Следующая ссылка о том, что определяет, в какой день года начинается номерная неделя . Нумерация недель (Википедия) . Это эффективно объясняет, почему 1 января этого года соответствует 52 неделе ISO. Последовательность %Vформатов, используемая «неизвестным пользователем», сообщает номер недели ISO.
Peter.O

Ответы:


4

Действительно некрасиво и, вероятно, работает только с GNU date:

date -d "$( date -d "$( date +'%Y-01-01' ) +40 weeks") -$( date -d "$( date +'%Y-01-01' ) +40 weeks" +'%w' ) days+1 day" +'%Y-%m-%d'

Протестировано только для вашего примера 3 октября, может не работать в некоторых других случаях.


Обновление : если у вас неязыковая локаль, вам нужно указать выходные данные из внутренней даты, чтобы приступить к работе. (И% F - это ГГГГ-ММ-ДД).

date -d "$(date -d "$(date +'%Y-01-01') +40 weeks" +"%F") -$(date -d "$(date +'%Y-01-01') +40 weeks" +%w) days +1 day" +"%F"

1
Вы пропустили форматирование вывода из внутренней даты, чтобы внешняя могла использовать ее правильно.
Йохан

@Johan, у меня не было проблем с использованием формата по умолчанию. Может быть, это специфический язык? Я использую en_US. Хороший вопрос в любом случае.
manatwork

Для даты я использую шведскую локаль, так что есть разница.
Йохан

Спасибо за корректировку локали. У меня есть пользовательский формат даты, и у меня была та же проблема. Я почти разобрался с ней, но теперь, когда вы ее опубликовали, я буду использовать ваш твик; лучше.
Peter.O

Там не было требования для этого, чтобы быть одним вкладышем. Было бы лучше разделить это на несколько строк, используя временные переменные с описательными именами, чтобы было понятно, как это работает. Предполагается также, что 1 января каждый год находится в том же номере недели, что не так, как уже отмечал @ Peter.O.
Адам Спирс

5

Альтернативный подход:

date --date "+$((40-$(date +%V)))weeks last monday"  +"%F"
  • 40 неделя, которую вы ищете
  • date +% V возвращает текущую неделю (35)
  • 40-35 = 5, то есть количество недель, чтобы добавить
  • оттуда искать последний понедельник

хороший, и он работает с моей пользовательской настройкой даты.
Peter.O

Это умная идея, но она не работает. Например, если сегодня понедельник на неделе 41 (т.е. date +%Vвозвращается 41), то --dateзначение параметра будет +-1weeks last monday, что на самом деле две недели назад, а не 7 дней назад.
Адам Спайерс

Я не уверен, понимаю ли я вашу критику. Это 2013 год, так что пример из вопроса не подходит. Какой должна быть абсолютная дата для вопроса, и что вместо этого возвращает мой подход (возможно: почему)?
пользователь неизвестен

@AdamSpiers: Мой календарь отображается как понедельник, неделя 40 и 30 сентября. Это то, что дает мой алгоритм (сегодня).
пользователь неизвестен

@userunknown Это потому, что вы тестируете свой код сегодня, т.е. во вторник, который наступает после понедельника. Если бы вы тестировали свой код вчера, он сломался бы. Чтобы сделать это более очевидным, попробуйте запустить date -d 'last monday'. Он вернется вчера. Как вы думаете, что бы сказал, если бы вы запустили его вчера?
Адам Шпирс

1

Хорошо, вот моя попытка Он крадет идеи из других ответов и пытается упростить логику. Это основано на системе ISO 8601, поэтому она не будет корректной, если вы живете в таких странах, как США или Канада, но должна быть легко настраиваемой для этих стран.

# sets $week_start to a representation of Monday of the given week
# number formatted via the given format, and similarly sets
# $week_end to Friday of the same week.
get_week_range () {
    week_num="$1" date_format="$2"

    # Most of the world adhere to ISO 8601 which states that weeks begin on Monday
    # and Jan 4th is always in week #1:
    #
    #   http://en.wikipedia.org/wiki/ISO_week_date
    #
    # For other week numbering systems (e.g. USA, Canada), see:
    #
    #   http://en.wikipedia.org/wiki/Seven-day_week#Week_numbering
    day_in_week_1=$( date +'%Y-01-04' )
    day_num_in_week_1=$( date -d $day_in_week_1 +%u ) # 1 is Monday
    days_from_week_1_start=$(( $day_num_in_week_1 - 1 ))
    # This is a Monday:
    start_of_week_1=$( date -d "$day_in_week_1 - $days_from_week_1_start days" +%F )

    week_delta="$(( $week_num - 1 ))"
    # Monday:
    week_start=$( date -d "$start_of_week_1 + $week_delta weeks"          +"$date_format" )
    # Friday:
    week_end=$(   date -d "$start_of_week_1 + $week_delta weeks + 4 days" +"$date_format" )
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.