bash скрипт зацикливание дат застревает? - PullRequest
0 голосов
/ 12 марта 2020

Я использую скрипт bash ниже, чтобы запустить программу python. Он проходит через дату / время именно так, как я и ожидал. Но затем он застрял в «2018-11-04 01:45:00». Добавление 15 минут к «2018-11-04 01:45:00» возвращает «2018-11-04 01:00:00», а не «2018-11-04 02:00:00». Кто-нибудь испытывал это?

    #!/bin/bash

    dEND=$(date +"%F %T" -d "2020-03-15 00:00:00")
    dCUR=$(date +"%F %T" -d "2018-11-04 01:00:00")
    echo $dCUR $dEND

    typeset -i sEND=1
    typeset -i sCUR=0
    echo $sCUR $sEND

    while( (( $sCUR < $sEND )) );do
       dCUR=$(date +"%F %T" -d "$dCUR 15 minutes")

       typeset -i sEND=$(date +%s -d "$dEND")
       typeset -i sCUR=$(date +%s -d "$dCUR")
       echo $dCUR $dEND $sCUR
    done
    echo done
    $ dCUR=$(date +"%F %T" -d "2018-11-04 00:00:00")
    $ echo $dCUR
    2018-11-04 00:00:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 00:15:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 00:30:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 00:45:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:00:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:15:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:30:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:45:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:00:00

Ответы [ 3 ]

2 голосов
/ 12 марта 2020

Я подозреваю, что вы (или, точнее, ваша машина ) могут быть расположены (или, точнее, настроены как , если он расположен) на Багамах, Бермудские острова, Бразилия , Канада, Куба, Фиджи, Гренландия, Гаити, Мексика, острова Сен-Пьер и Микелон, острова Теркс и Кайкос, и США.

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


Этот ваш код прекрасно работает в моей системе, но мой географический регион не обеспечивает переход на летнее время.

Это во многих местах переключение происходит примерно в 2-3 часа ночи, поэтому оно может быть просто артефактом выбранной вами даты. На этой странице здесь видно, что несколько мест действительно сделали переход 4 ноября (отсюда мой список мест в первом абзаце этого ответа).

Вы, вероятно, можете это подтвердить проведя точно такой же эксперимент, но используя 5 ноября, а не выбранную вами дату. Вы также можете добавить спецификатор формата %z, и вы увидите, что он изменится (например) +08 на +07.


Как и в случае большинства проблем с мировое время, лучшее решение - как можно быстрее преобразовать все местное время в UT C и превратить их в местное время как можно позже. Таким образом, у вас в основном будет постоянная временная база, за исключением случаев, когда вы взаимодействуете с конечными пользователями (которые обычно думают с точки зрения местного времени).

В качестве примера, вот сценарий, который выполняется с 1:00 до 5:00, в регионе с переключателем часового пояса в диапазоне.

#!/bin/bash

# My region doesn't do DST but New York does, so fake it.

export TZ=America/New_York

# Helper functions for UTC/local conversion.

utcFmt="%F %T %z"
localFmt="%F %T"

utcToLocal() {
    echo "$(date +"${localFmt}" -d "$(date +"${utcFmt}" -d "$1")")"
}

localToUtc() {
    echo "$(date -u +"${utcFmt}" -d "$(date +"${utcFmt}" -d "$1")")"
}

# Init UTC values based on local time.

utcCur="$(localToUtc "2018-11-04 01:00:00")"
utcEnd="$(localToUtc "2018-11-04 05:00:00")"

echo "Going from ${utcCur} to ${utcEnd}"

while [[ "${utcCur}" < "${utcEnd}" ]] ; do
    # Display local time, but adjust UTC time.

    echo "At $(utcToLocal "${utcCur}")"
    utcCur="$(date -u +"${utcFmt}" -d "$utcCur 15 minutes")"
done

Как видно из выходных данных, есть один откат к более раннему времени, потому что это то, что происходит, когда вы переводите часы назад (см. * маркеры):

Going from 2018-11-04 01:00:00 to 2018-11-04 05:00:00
At 2018-11-04 01:00:00
At 2018-11-04 01:15:00
At 2018-11-04 01:30:00
At 2018-11-04 01:45:00
At 2018-11-04 01:00:00 * Roll back one hour (once).
At 2018-11-04 01:15:00
At 2018-11-04 01:30:00
At 2018-11-04 01:45:00
At 2018-11-04 02:00:00 * Keep going.
At 2018-11-04 02:15:00
At 2018-11-04 02:30:00
At 2018-11-04 02:45:00
At 2018-11-04 03:00:00
At 2018-11-04 03:15:00
At 2018-11-04 03:30:00
At 2018-11-04 03:45:00
At 2018-11-04 04:00:00
At 2018-11-04 04:15:00
At 2018-11-04 04:30:00
At 2018-11-04 04:45:00

И, если вы go до другого конца летнего времени (где час исчезает), вы можете увидеть это также ( снова посмотрите на маркеры *:

utcCur="$(localToUtc "2018-03-11 01:00:00")"
utcEnd="$(localToUtc "2018-03-11 05:00:00")"

Going from 2018-03-11 01:00:00 to 2018-03-11 05:00:00
At 2018-03-11 01:00:00
At 2018-03-11 01:15:00
At 2018-03-11 01:30:00
At 2018-03-11 01:45:00
At 2018-03-11 03:00:00 * Put clock foward one hour.
At 2018-03-11 03:15:00
At 2018-03-11 03:30:00
At 2018-03-11 03:45:00
At 2018-03-11 04:00:00
At 2018-03-11 04:15:00
At 2018-03-11 04:30:00
At 2018-03-11 04:45:00
1 голос
/ 12 марта 2020

2018-11-04 было первое воскресенье ноября. Регионы Северной Америки и близлежащие территории, которые переключаются между летним и стандартным временем, в настоящее время делают это в первое воскресенье ноября (и во второе воскресенье марта для другого перехода). Это означает, что в ноябре время идет с 01:59:59 xDT до 01:00:00 xST (весна вперед; падение назад). Дополнение и результат верны - даже если это не то, что вы ожидали.

Места в Европе, которые в настоящее время переключаются на весну в последнее воскресенье марта и отступают в последнее воскресенье октября, изменяя таким образом 2 или на 3 недели позже весной и на 1 неделю раньше осени, чем в США. Если 1 марта выпадает с понедельника по четверг, разрыв составляет 2 недели; С пятницы по воскресенье, 3 недели.

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

0 голосов
/ 12 марта 2020

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

Чтобы сделать то, что вы хотите, преобразовать дату в количество секунд с начала эпохи, добавить 15*60 секунд, а затем преобразовать вернуться к нужному формату.

Это будет:

dCUR=$(date -d "@$(($(date --date="$dCUR" +%s) + 15 * 60))" +"%F %T"); echo $dCUR
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...