Bash: Shell Script: Узнайте, является ли текущий (юлианский) день последним днем ​​месяца - PullRequest
0 голосов
/ 14 апреля 2020

У меня есть требование, когда мне нужно запускать определенные процессы в конце каждого месяца. Я получаю дату в качестве Ввода от предыдущего процесса, а дата в юлианском формате (например, 2020105 CCYY DDD). Мне нужно проверить, прошла ли дата в конце месяца. Я имею в виду 2 варианта:

  1. Непосредственно проверить, является ли юлианская дата датой окончания месяца.
  2. Преобразовать юлианскую дату в григорианскую или обычную дату, а затем проверить, является ли она концом месяца.

В любом случае, пожалуйста, приведите мне некоторые материалы, на которые я могу ссылаться.

Я знаю, что могу получить текущую дату, используя echo $(date '+%Y-%m-%d'), а затем проверить, является ли она последней день месяца Но мне нужно строго учитывать юлианскую дату, которая поступает в качестве входных данных для моего процесса, поскольку она отправляется Бизнесом.

Заранее спасибо за помощь.

1 Ответ

1 голос
/ 15 апреля 2020

Если у вас есть дата Gnu, вы можете использовать следующую функцию:

next_day_of_month () { 
    date -d "${1:0:4}-01-01 $((10#${1:4:3})) days" +%-d
}

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

Если вам нужно чистое bash решение (которое, несмотря на то, что оно не вызывает никаких внешних утилит, серьезно медленное), вы можете использовать следующее.

Существует не очень сложная формула, которая может быть использована для вычисления месяца, соответствующего номеру дня, но требует подсчета дней, начиная с предыдущего 1 марта, а не с 1 января. Корректировка номера дня таким образом требует знания того, является ли год високосный год или нет, что делает все немного сложнее.

В любом случае, вот оно. [Примечание 1]

# Compute the month number (1-12) corresponding to a day in
# in "Julian" format YYYYJJJ (001 == Jan. 1; 365/6 == Dec. 31)
# Yes, I know it's full of magic numbers.
month_for_julian_day () { 
    local -i y=${1:0:4} j=10#${1:4:3} march1=60
    if (( y % 400 == 0 )) || ! (( y % 100 == 0 )) && (( y % 4 == 0)); then
        march1=61
    fi
    if (( j >= march1 )); then j=j-march1; else j=j+305; fi
    local -i m=(j*5+461)/153
    if (( m > 12 )); then m=m-12; fi
    echo $m
}

Чтобы использовать это, было бы удобно иметь

# Advance a Julian date to the next day.
# Note: this one doesn't wrap around. Because of the way it's used
# here, that doesn't matter.
julian_next() { printf "%s%03d" ${1:0:4} $((10#${1:4:3})); }

Тогда вы можете определить

# Succeeds if the Julian date is the last day of a month
is_last_day_of_month() {
    (( $(month_for_julian_day $j) != $(month_for_julian_day $(next_julian $j)) ))
}

Примечания:

  1. После того, как я вставил это, я заметил, что используемая здесь подсветка синтаксиса думает, что # запускает комментарий. Это не правда. # только начинает комментарий, если это первый символ в слове. В этом случае присвоение j=10#${1:4:3} заставляет интерпретировать последние три цифры предоставленной даты в базе 10.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...