Верстакфорум практиков
рекламаiprazon: приватные серверные адреса IPv4 и SOCKS5, безлимитный трафик, бесплатный тест до 2 часов
ФорумСкрипты и автоматизация

Даты в скриптах: где чаще всего ошибаются

Дарья Смолина
Дарья Смолина
Участник
сообщений 340
с дек
1 сентября, 08:32первое сообщение

Собираю статистику по ночным выгрузкам, складываю в папки по дате. Всё шло ровно до ночи перевода часов. Наутро обнаружила две папки за одно и то же число, а следующая ночь вообще пропала из отчёта.

Стала копать и поняла, что даты у меня везде сделаны по-разному: где-то беру системное время машины, где-то время из ответа сайта, где-то просто складываю строку из кусков. Пока склеивала на коленке, вопросов не возникало.

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

Артур Вагнер
Артур Вагнер
Знаток
сообщений 1290
с мая
8 февраля, 11:49#2

Ваш случай с переводом часов лечится одной привычкой: внутри скрипта живёт только UTC. Локальное время появляется на самом последнем шаге, когда человек смотрит на экран.

Имена папок тоже берите из UTC. Тогда двух папок за одно утро не будет никогда.

конфиг без комментария это загадка
Дарья Смолина
Дарья Смолина
Участник
сообщений 340
с дек
15 июля, 14:06#3
Артур Вагнер: внутри скрипта живёт только UTC

А сравнение с датой из ответа сайта? Там приходит строка со смещением, каждый сайт пишет по-своему.

Артур Вагнер
Артур Вагнер
Знаток
сообщений 1290
с мая
22 декабря, 17:23#4

Разбирайте её в момент чтения и сразу приводите к UTC, дальше по коду ходит уже приведённое значение.

from datetime import datetime, timezone
from email.utils import parsedate_to_datetime

s = "Tue, 04 Mar 08:41:02 +0300" # из заголовка письма d = parsedate_to_datetime(s) # со смещением u = d.astimezone(timezone.utc) # к общему знаменателю print(u.isoformat()) ```

Правило простое: строка со смещением живёт ровно одну строчку кода. Дальше только приведённое.

конфиг без комментария это загадка
hexdump
hexdump
Знаток
сообщений 940
с июн
1 мая, 08:40#5

Моё любимое место, где спотыкаются все по очереди: сравнение дат строками.

Пока формат ГГГГ-ММ-ДД, строки сравниваются правильно и сортируются правильно. Стоит появиться формату ДД.ММ.ГГГГ, и сортировка честно ставит третье марта раньше двадцать восьмого февраля, потому что она смотрит на первый символ. Ловится это не сразу, потому что месяц-другой данные могут ложиться удачно.

Света Панина
Света Панина
Новичок
сообщений 160
с мар, второй сезон
8 октября, 11:57#6

а isoformat это то же самое, что и такой порядок?

hexdump
hexdump
Знаток
сообщений 940
с июн
15 марта, 14:14#7

Да, там как раз год, месяц, день через дефис. Потому его и берут для имён файлов: сортировка по имени сразу даёт сортировку по времени.

Борис Лапин
Борис Лапин
Знаток
сообщений 1960
с мар
22 августа, 17:31#8

Накину ещё три штуки, которые ловил руками.

Первое. Арифметика через «плюс восемьдесят шесть тысяч четыреста секунд». В сутках столько секунд бывает не всегда: перевод часов, високосная секунда. Прибавлять надо календарные сутки средствами библиотеки, а секунды оставить для замеров длительности.

Второе. Конец месяца. Классика это тридцать первое января плюс месяц. Библиотеки отвечают по-разному, кто-то даёт последний день февраля, кто-то ругается. Проверяйте, что именно делает ваша.

Третье. Границы суток при выборке. Когда пишете условие «за вчера», очень легко получить окно от полуночи до полуночи включительно с двух сторон и посчитать одну запись дважды. Нижняя граница включительно, верхняя строго меньше следующей полуночи, других вариантов не бывает.

границы суток без перекрытия
границы суток без перекрытия
ostrov
ostrov
Участник
сообщений 505
с окт
1 января, 08:48#9

плюсую про сутки в секундах, у меня на этом отчёт разъехался на час дважды за сезон

gremlin_dv
gremlin_dv
Знаток
сообщений 1840
с мар
8 июня, 11:05#10

Ещё мелочь для тех, кто пишет на bash и таскает скрипты между машинами: date -d понимает человеческие фразы вроде yesterday далеко не везде. На макбуке коллеги тот же скрипт лёг сразу.

# работает и там, и там
python3 -c 'import datetime as d; print((d.datetime.now(d.timezone.utc).date()-d.timedelta(days=1)).isoformat())'

Некрасиво, зато одинаково себя ведёт.

три монитора и ни одного свободного
Дарья Смолина
Дарья Смолина
Участник
сообщений 340
с дек
15 ноября, 14:22#11

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

Папки переделала, ночь перевода часов теперь проходит незаметно. Спасибо всем, кто накидал.