Комментарии 49
Конечно есть.
Если проект с C++11, то в chrono
есть std::chrono::steady_clock
. Если на более старом стандарте, то нужно использовать системные вызовы целевой ОС (вроде clock_gettime
с CLOCK_MONOTONIC
на *nix или QueryPerformanceCounter
на винде).
К слову, все это легко находится в гугле по запросу "monotonic time c++/c++03/windows/unix".
Спасибо.
P.S. Вторая часть очень опосредованно относится к времени)
С неправильным временем у пользователя был занятный кейс. Мы делали некий продукт для небогатых, в основном, компаний, и он был сильно завязан на корректное время. Дело было в начале '10-ых, в России недавно переколбасили часовые пояса, а у всех была пиратская винда, которая не обновлялась и в ней не было новой tzdata. Приходилось брать время из ответов сервера, вводить поправку на сетевую задержку, вычислять смещение часового пояса и плясать с бубном, потому что в JS есть getTimezoneOffset
, но нет setTimeZoneOffset
...
Спасибо за статью!
Работа со временем — очень важная вещь.
Сам давно задумывался над этим и пытался выработать решения на распространенные кейсы, плюс на обработку краевых случаев.
Радует, что одни и те же мысли приходят одновременно разным людям.
Хочется, однако, риторически прокомментировать вот это :
Так линейно вы, в общем, и пишете код. Дата начала — сегодня минус одни сутки, дата окончания — сегодня. Казалось бы, все работает, но потом ровно в полночь у вас случается странное. У вас дата начала вот здесь. Дата начала минус одни сутки — получается, такая. После этого почему-то дата окончания отчета совершенно другая.
Вы, а точнее ваш начальник получаете отчет за двое суток вместо одних. Технический начальник и менеджер приходят, жалуются и вежливо предлагают вам через шесть месяцев перейти в другую команду.
Абсолютно типовая ошибка, проистекающая из неаккуратности, нежелании разобраться в природе вещей (времени в данном случае), низкой культуры кодирования, незнания и нежелания разобраться в реализации стандартной библиотеки, и как она (реализация) маппится на ту самую природу вещей.
Но… Скажите, где вы находите компании, где за такое просят покинуть команду или лучше компанию?
Сколько помню, везде в энтерпрайзе попадался именно код такого характера, со временем, включая прямо вот описаную вами ошибку, другие типовые ошибки со временем и другими сущностями.
И что характерно, авторы такого кода были всегда в почете (такой код можно писать быстро, перформанс наше все! — почти ж никто в ИТ не в курсе, что нужно перформанс для разрабов нужно переводить вторым главным значением — "эффективность", а не первым "производительность", интерпретируемую как скорость закрытия тасков на гора, а дальше не волнует).
Другое дело, что, как правило, авторы такого кода были уже далече, только не их попросили, а они на гребне волны славы сами успели уйти на повышение — в другие компании, реже в той же компании.
И в других фреймворках с другими методами life cycle то же самое логично. Когда у вас происходит какой-то destruct, destroy, еще что-нибудь, unmount, надо корректно такие вещи не забывать чистить за собой.
А ещё можно использвать фреймворки, которые чистят всё автоматически, а не полагаются, что разработчик ничего не забудет..
слышали, хотя бы, про функциональный подход, про чистые функции, про отсутствие side-эффектов
эти два запроса асинхронных, они явно друг от друга не зависят
Вы бы хоть определение чистой функции почитали..
Изучайте качественный код, в том числе опенсорс — Lodash, RxJS и т. п.
https://github.com/lodash/lodash/blob/master/.internal/createRound.js
https://github.com/ReactiveX/rxjs/blob/master/src/internal/util/ArgumentOutOfRangeError.ts
Очень "качественный" код..
использвать фреймворки, которые чистят всё автоматически, а не полагаются, что разработчик ничего не забудет
Есть пример такого фреймворка? Если опишете, как там реализована очистка всего и защита от вызовов после разрушения компонентов — будет отличная статья.
То есть вас не смущает, что для всех округлений чисел там используются строковые операции?
Со сравнением производительности
В идеале, конечно, сделать PR, но можно и просто здесь код показать
console.log(_.round(4.006, 2)); // 4.01
console.log(floor(4.006, 2)); // 4
console.log(_.round(4060, -2)); // 4100
console.log(floor(4060, -2)); // 4000
Вы точно проверяли свой код? Он работает неверно и не является заменой лодашевскому
Разные названия функций вас не смутили?
Не понял, то есть вы недовольны одним кодом, а привели пример переписывания другого?
А давайте вы прежде чем бросаться защищать "качественную" библиотеку, ознакомитесь с её исходниками?
https://github.com/lodash/lodash/blob/master/floor.js
Я не бросаюсь её защищать. Я прошу обосновать утверждение о том, что приведённый пример действительно плох.
Вы привели в пример функцию, которая используется в round. В floor тоже, да. Но ещё и в round. И если я правильно понял, вы хотели показать пример как переписать её "красиво". Естественно, не лишая её имеющейся функциональности
Может я не увидел чего-то по вашей ссылке, или не понял. Но мне показалось, что функциональности round в вашем коде нет. Прошу прощения, если не заметил, и ткните тогда пальцем в виде размещения этого кода здесь
А давайте вы самостоятельно замените floor на round в обеих реализациях и убедитесь, что ничего принципиально не изменится? Продолжать этот диалог мне не интересно, удачи вам по жизни.
Ещё непонятнее стало. Где ваш код round то? По вашей ссылке я вижу тот же "говнокод" со строками. Что на что вы предлагаете мне заменить?
Я допускаю, что не могу посмотреть ваш код, и вижу только код лодаша, потому что либо не разобрался в интерфейсе, либо в мобильном браузере что-то идёт не так. Но вы упорно отказываетесь показать свой код прямо здесь, и поэтому я до сих пор так и не увидел вашу красивую версию ф-ии round
Почему для Math.round()
использованы строковые операции, описано комментарием прямо в исходнике — из-за не всегда верного округления Math.round. Например, попытка округления 1.005 до двух знаков после запятой "решением в лоб" Math.round(1.005 * 100) / 100
даст ровно 1, а _.round(1.005, 2)
даст правильное значение 1.01.
Ошибаются в инкрементах на неделю, месяц, год в последних днях месяца. 31-01-2019 + 1 месяц = 31-02-2019 = 03-03-2019. Иногда забывают про високосные годы.
Ошибки инкремента даты делают при переходах между зимним и летним временем. Мы же помним, что время подвластно политикам и правила могут меняться год от года.
Отдельная тема — часовые пояса. Какой сейчас день? А где именно? Вот уж действительно начинаешь понимать, что живёшь в пространственно-временном континууме. Чтобы определить «когда» нужно знать «во сколько» и «где». Хранить информацию о времени в unix timestamp может быть не лучшей идеей. Нужно сто раз взвесить, прежде чем решать приводить все к UTC.
На самом деле, не имея информации о часовом поясе и актуальной версии tzdata вы мало, что можете правильно посчитать. Рассчет на сервере и на клиенте может давать разные результаты. После очередного апдейта tzdata результаты могут сильно измениться.
Так же хлопот доставляют форматы записи дат в разных локалях. 10/11/12 без контекста не распарить.
Но ведь обычно timestamp это количество (милли) секунд, прошедших с конкретного момента времени. Для него нет таймзоны. Где бы я ни находился, в Сеуле или в Лондоне, количество секунд будет одинаково
Но вы писали
на фрон приходит дата в timestamp… если таймзона на беке оказалась не та— я только это и хотел отметить. У timestamp нет часового пояса
Странно что не упомянуты еще типичные грабли:
Запрос в БД с указанием ТОЛЬКО дат диапазона, когда в поле в БД включает еще и время. Типично от получается в запросе поле времени по умолчанию 00:00:00 до 00:00:00, а нужно, как правило, от 00:00:00 до 23:59:59. Очень типичная ошибка.
Запрос из браузера выборки по диапазону времени. А времени чего? От TZ браузера? От TZ БД? От Гринвича/MSK? А вообще чего нужно то? Полночь в России наступает в разное время.
Кстати, типично, что в большинстве протоколов "нарисованных" разработчиками из Москвы отсутствует таймзона как сущность воооообще.
А на вопрос "а в какой TZ время то указывать?" вызывает ступор. Как будто другой TZ кроме MSK не бывает и не важно где (TZ) по факту событие произошло. Особенно не важно это для фродмониторинга <сарказм>
Особенно весело, когда встает вопрос про отчеты для банка у которого филиалы и в Москве и Владивостоке и слияние недавно произошло. Вопрос не технический. Организационный.
И по моему мнению, больше всего проблем с TZ возникает.
Например в таком простом вопросе "Хочу видеть транзакции за вчера. Филиалы у нас в Барнауле, Москве и Владивостоке, а терминалы по всей России".
А вам слабо объяснить сотруднику в Барнауле, почему список транзакций за день у него и сотрудника в Москве разный при одном подходе (список исходя из TZ браузера оператора).
Или почему он не видит транзакцию сделанную сегодня ночью (вот же она на чеке) в списке транзакций за сутки при другом подходе (список, исходя из TZ головного филиала в Москве).
И начинается… ваш софт г-но и выдает ерунду. "Хотим кнопку счастья для любого тупого сотрудника."
Иногда кажется что у многих абстрактное мышление отсутствует как класс..
поле времени… нужно, как правило, от 00:00:00 до 23:59:59
Кстати, здесь может быть ещё одна ошибка, если время хранится не округлённым до секунды.
Например, если время хранится с точностью до миллисекунды, то надо задавать диапазон времени от 00:00:00 до 23:59:59.999
Как вариант, чтобы меньше вспоминать о точности хранения времени, можно задавать конечную дату в запросе как "меньше 00:00:00 следующего дня", а не "меньше или равно 23:59:59.999 текущего дня".
Если уж упомянули ее, было бы неплохо кратко хотя бы пробежаться по особенностям и фичам при работе с временем/календарем. Уж до 8й версии там было о чем рассказать, это точно. А это до сих пор больше половины всех проектов. А может и больше.
Можно было бы конечно реализовать временные отметки не в абсолютном времени, а в относительно, типа сколько времени прошло от старта большого процесса.
Но часто удобнее просто поискать по локальному времени, чем искать начало и считать смещение.
Есть ещё такая экзотическая штука как "высокосная секунда". Встречается нечасто и мало кому мешает. Но мне как-то изрядно выпила крови при синхронизации времени двух телецентров.
Тяжёлое бремя времени. Доклад Яндекса о типичных ошибках в работе со временем