Pull to refresh

Работа с датой. PHP5.2

PHP *
В PHP5.2 для работы с датой/временем появились классы DateTime и DateTimeZone. Вначале на них не обратил внимание, так как привык пользоваться функциями date(), etc. Но потом решил все-таки посмотреть какие возможности реализуют новые классы.

DateTime


Конструктор класса


DateTime DateTime::__construct ([ string $time [, DateTimeZone $timezone ]] )

Конструктор принимает два параметра:
1. Строка в формате принимаемым strtotime(), по умолчанию — «now».
2. Зона для которой будем считать время.
Читать дальше →
Total votes 54: ↑45 and ↓9 +36
Views 14K
Comments 46

Осторожность с датой не помешает

PHP *
imageМне для своего проекта, на php, всегда надо точно знать какой номер недели сейчас. Я пользовался командой date() для этого и получал год и номер недели. Например 22 декабря 2008 года была 52 неделя года. просто замечательно все было пока не пришло 29 число. Потому 29 декабря 2008 года идет как неделя 00, что мягко говоря неправильно. Поэтому я окончательно уверился в том, что для точных и калледарных вычислений data вовсе не подходит. Больше всего подходит функция strftime(’%W’);
Читать дальше →
Total votes 69: ↑61 and ↓8 +53
Views 838
Comments 44

Хранение даты в mysql с учетом часового пояса

MySQL *
image
Статья о том, как избежать путаницы с датами, хранимыми в mysql.
Эти путаницы возникают по двум причинам:
1. Разные территории нашей планеты имеют разный сдвиг времени.
2. Некоторые страны переходят на летнее время и обратно(карта со странами, переходящими на летнее время).

Многие решают эти проблемы по-разному. Кто-то делает сдвиг даты в SQL запросах, кто-то в php. Кто-то хранит даты в TIMESTAMP, кто-то в DATETIME. Я переискал много источников, но нигде не нашел верного решения данной проблемы на русском. В родной документации по mysql нашел информацию о том, как добиться корректной автоматической конвертации TIMESTAMP в локальное время, но тут тоже свои подводные камни.

Если в php настройка временной зоны делается просто, в mysql возникают сложности, особенно, если доступ к mysql серверу вам ограничен и там еще не установлены некоторые таблицы.
Читать дальше →
Total votes 13: ↑9 and ↓4 +5
Views 33K
Comments 8

Календарные типы данных в MySQL: особенности использования

MySQL *
В MySQL 5 есть несколько типов данных для хранения даты и времени. Это TIMESTAMP, DATE, DATETIME, TIME и YEAR. Все они обладают своими особенностями, и выбор в пользу того или иного календарного типа должен производиться отдельно в каждой конкретной ситуации. Я хотел бы поделиться с вами результатом моего сегодняшнего миниисследования этих типов, в том числе в аспекте работы с временными зонами.


Читать дальше →
Total votes 39: ↑22 and ↓17 +5
Views 67K
Comments 8

Форматирование даты по RFC-2822 для RSS в ASP-vbscript

Lumber room
Настоящий текст не является призывом к использованию javascript, vb (чур меня), IIS, RSS, HTTP, TCP, IP и других нерусских слов, а описывает частное решение частной проблемы.

Довелось на днях привинчивать RSS для Яндекс-новостей к сайту на ASP (vbscript). Все, в общем-то, было просто, но нежданно-негаданно запнулся на ровном месте — форматировании даты. Дата (pubDate) должна быть в формате RFC-2822, причем в требованиях Яндекса указано, что время должно быть не UTC, а с правильным часовым поясом, соответствующим размещению ресурса. Например: Fri, 25 Dec 2009 09:24:44 -0300. Известное дело, vbscript сам c датой работать толком не умеет: знает полтора ущербных формата, да и те норовит по своей прихоти испохабить локализацией (сам был свидетелем случаев, когда при логине пользователя в консоль сервера IIS+ASP+vbscript хватал локаль зашедшего юзера, менял формат даты и всего остального, после чего приложение с грохотом валилось). Надо было сформатировать дату, не пользуясь медвежьими услугами барсика, и я пошел в Инет в рассуждении быстро нарыть подходящий код, а потом перейти к содержательной работе.
Щас!
Читать дальше →
Total votes 6: ↑1 and ↓5 -4
Views 1.3K
Comments 4

Неявная установка значения объекта Date?

Lumber room
Задача: получить вчерашний день и день_неделю_назад на JavaScript'е. Пишу простой скриптик:
var dateToday = new Date();
var tmpDate = new Date();

tmpDate.setDate(dateToday.getDate() - 8);
alert(dateToday); // <- Jun 07, OK
alert( tmpDate ); // <- May 30, OK

tmpDate.setDate(dateToday.getDate() - 1);
alert(dateToday); // <- Jun 07, OK
alert( tmpDate ); // <- May 06, Oooops!


Казалось бы, что тут особенного? Давайте посмотрим, чего я хотел и что получил:
— Создаю два разных объекта типа Date и записываю их в переменные dateToday и tmpDate. Сейчас здесь находится «сегодня»;
— Устанавливаю значение tmpDate в (dateToday — 8 дней), т.е. если сегодня 7 июня, то это получается 30 мая, всё верно. Выводит значение tmpDate — действительно, 30 мая;
— Теперь я хочу получить вчерашний день. Беру значение dateToday (оно нигде не менялось и хранит день сегодняшний) и вычитаю из него 1 день. Я должен получить 6 июня;
— Alert выводит 5 мая!

В чём причина такого странного поведения скрипта? А в том, что у объекта Date свойства день, месяц, год, час и т.п. никак не взаимосвязаны, поэтому первая установка выставила месяц = 5, день = 30, а вторая — только день = 5. Отсюда и получаем 5 мая.

Что делать? Заново инициализировать переменную перед вторым действием. Т.е.:
var dateToday = new Date();
var tmpDate = new Date();

tmpDate.setDate(dateToday.getDate() - 8);
alert(dateToday); // <- Jun 07, OK
alert( tmpDate ); // <- May 30, OK

tmpDate = new Date();

tmpDate.setDate(dateToday.getDate() - 1);
alert(dateToday); // <- Jun 07, OK
alert( tmpDate ); // <- Jun 06, OK!


Для меня это была совершенно неочевидная вещь, потратил полчаса драгоценного времени ;)
Total votes 18: ↑14 and ↓4 +10
Views 245
Comments 3

Timestamp из даты-времени с помощью XSLT

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

В моем случае ничего криминального на горизонте не предвиделось: требовалось провести расчет времени между двумя событиями в иерархическом XML логе. Дата и время хранились в формате частично совместимом с RFC 3339.

Эта совместимость обеспечивалась корректной нотацией даты yyyy-MM-dd и времени hh:mm:ss.SS, но имели место следующие отступления от стандарта:
  1. Дата и время разделялись пробелом, а не буквой T;
  2. Число цифр, обозначающих миллисекунды могло варьироваться от «ниодной» до «много-много»;
  3. Часовой пояс не указывался вообще.
Сначала я хотел воспользоваться готовым решением с exslt.org – date:difference, но от него пришлось отказаться. Дело в том, что разницу требовалось получать с точностью до миллисекунд, а этот алгоритм возвращал валидный xsd:duration (ISO 8601), который миллисекунд не содержит. К тому же парсить чужой output, хоть и формализованный – дело не очень благодарное. Таким образом, покопавшись немного в exslt, я решил написать парсер сам, в надежде, что смогу сделать это быстро…
Читать дальше →
Total votes 7: ↑7 and ↓0 +7
Views 8.3K
Comments 7

Неправильное время на FreeBSD — это не страшно. UPD: И в PHP не страшно тоже

*nix *
Как всем известно, в 2011 году указом президента РФ был отменен переход на зимнее время. Тем не менее, 30 октября на многих компьютерах часы были переведены. Мы не будем выяснять почему нужные апдейты не были вовремя скачаны установлены (нерадивость админов или невозможность этой операции). Главное сейчас привести часы в актуальное состояние. Конкретно речь пойдет об ОС FreeBSD. Кого не минула чаша сия — прошу под кат.

Читать дальше →
Total votes 34: ↑27 and ↓7 +20
Views 21K
Comments 38

Двигаем время на лету для JVM

Java *
Sandbox
Наверное всем иногда приходилось сталкиваться с проблемой перевода времени на локальном компьютере для тестирования программ. Например, вам нужно проверить как сервер обработает платежи через неделю от сегодняшней даты.

Самый простой способ сделать это — подвинуть системное время. Но у него есть несколько недостатков. Некоторые программы, например, Skype, начинают глючить, сохранять сообщения далеко в будущее или в прошлое. Так же системными политиками может быть задано синхронизировать время с корпоративным сервером каждые 5 минут.
Читать дальше →
Total votes 22: ↑16 and ↓6 +10
Views 11K
Comments 9

Оптимизируем, оптимизируем и еще раз оптимизируем

Java *
По долгу службы мне периодически приходится пользоваться профайлером, так как требования к производительности серверов задокументированы и не могут опускаться ниже определенного уровня. Помимо некоторых очевидных архитектурных изменений и решений частенько находятся повторяющиеся места от модуля к модулю, от одного проекта к другому, которые создают дополнительную нагрузку на виртуальную машину, которыми и хочу поделиться.
Так уж случилось, что на глаза чаще всего попадался код работы с Date потому с него и начнем:

Date

Не один десяток раз я имел возможность наблюдать, как во время обработки одного запроса от пользователя в нескольких разных местах создается новый объект даты. Чаще всего цель одна и та же — получить текущее время. В простейшем случае это выглядит так:

    public boolean isValid(Date start, Date end) {
        Date now = new Date();
        return start.before(now) && end.after(now); 
    }

Казалось бы — вполне очевидное и правильное решение. В принципе, да, за исключением двух моментов:
  • Использовать Date сегодня в java — уже, пожалуй, моветон, учитывая тот факт, что почти все методы в нем уже Deprecated.
  • Нету смысла создавать новый объект даты, если вполне можно обойтись примитивом long:

    public boolean isValid(Date start, Date end) {
        long now = System.currentTimeMillis();
        return start.getTime() < now && now < end.getTIme(); 
    }


SimpleDateFormat

Очень часто в веб проектах возникает задача перевести строку в дату или наоборот дату в строку. Задача довольно типичная и чаще всего выглядит так:

    return new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z").parse(dateString);

Это правильное и быстрое решение, но если серверу приходится парсить строку на каждый пользовательский реквест в каждом из сотен потоков — это может ощутимо бить по производительности сервера в виду довольно тяжеловесного конструктора SimpleDateFormat, да и помимо самого форматера создается множество других объектов в том числе и не легкий Calendar (размер которого > 400 байт).

Ситуацию можно было бы легко решить, сделав SimpleDateFormat статическим полем, но он не является потокобезопасным. И в конкурентной среде легко можно словить NumberFormatException.

Вторая мысль — использовать синхронизацию. Но это таки довольно сомнительная вещь. В случае большой конкуренции между потоками, мы можем не просто не улучшить производительность но и ухудшить.

Но решения есть и их как минимум 2:
  • Старый, добрый ThreadLocal — cоздаем SimpleDateFormat для каждого потока 1 раз и переиспользуем для каждого последующего запроса. Данный подход поможет ускорить парсинг даты в 2-4 раза за счет избежания создания объектов SimpleDateFormat на каждый запрос.
  • Joda и ее потокобезопасный аналог SimpleDateFormat — DateTimeFormat. Хоть йода в целом и медленнее дефолтного Java Date API в парсинге дат они идут наравне. Несколько тестов можно глянуть тут.

Читать дальше →
Total votes 50: ↑38 and ↓12 +26
Views 23K
Comments 34

Даты в JavaScript: количество дней в месяце и некоторые особенности Safari

JavaScript *
Sandbox

Собственно, сам сниппет


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

На эту тему был нагуглен один изящный механизм, использующий одну известную особенность многих языков программирования. Если установить несуществующую дату для какого-либо месяца (например 31 апреля), то в результате нашем объекте будет сохранено соответствующее число следующего месяца (в данном случае — 1 мая).

Таким образом, для того, чтобы получить количество дней в указанном месяце, необходимо отнять результат вышеописанной операции из числа 32. То есть, если задать в качестве даты 32 апреля, в результате мы получим 2 мая. Проверим: 32-2=30 — такое количество дней будет в апреле.

	var days_in_april = 32 - new Date(2013, 3, 32).getDate();

Читать дальше →
Total votes 26: ↑14 and ↓12 +2
Views 44K
Comments 37

Проблемы даты и времени в JS

JavaScript *


Редкому программисту случается избежать работы с датой и временем. Вообще, дата/время — базовое понятие и в основной массе языков существуют встроенные механизмы работы с этим типом данных. Казалось бы, JS не исключение, есть встроенный тип Date, есть куча функций в прототипе, однако…
Читать дальше →
Total votes 52: ↑38 and ↓14 +24
Views 83K
Comments 55

Проблема «7-го января»

Website development *JavaScript *Browsers
Во время работы над одним из проектов обнаружился довольно интересный баг, который, как потом выяснилось, проявляется не только в «самописных» календарях, но и в популярных open-source библиотеках. Проблема заключается в невозможности выбрать 7 января. В некоторых календарях эта дата просто отсутствует:
image
Если выбирать 6-е число (которое стоит на месте 7-го), то выбирается… 6-е число.

Баг наблюдается (по предварительным оценкам) под Windows 8.

UPD: Природа проблемы раскрыта здесь. Все дело в RTZ2 после Microsoft Update KB2998527.

UPD2: 0xy: проблема наблюдается не только в Firefox, но и в мобильных версиях различных браузеров. Подробнее (плюс баг-фикс).

Некоторые подробности под катом.
Читать дальше →
Total votes 55: ↑40 and ↓15 +25
Views 42K
Comments 31

$mol_time — работаем с датами и временем правильно

JavaScript *Designing and refactoring *Algorithms *
Recovery mode
Здравствуйте, меня зовут Дмитрий Карловский и я… очень стар. Годы уже не те, чтобы с лёгкостью разбираться в хитросплетениях мудрёных интерфейсов. Хочется чего-то относительно простого, но и достаточно мощного, чтобы не чувствовать себя калекой, который еле-еле пишет простейшую программу.

В любом приложении рано или поздно появляется необходимость работы со временем: распарсить, как-то модифицировать, что-то вычислить, сериализовать. Дата и время — это довольно сложные штуки, которые подстраиваются под солнечные, лунные и земные циклы одновременно. При этом в году может быть разное число дней, а в дне — разное число часов, даже в минуте не всегда 60 секунд. Из-за этого работа со временем требует от программиста повышенной аккуратности и всё-равно баги будут всплывать ещё очень долго.

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

Далее вы узнаете, как я избавился от геморроя путём смены городского минивена на спортивный велосипед :-)
Читать дальше →
Total votes 21: ↑18 and ↓3 +15
Views 11K
Comments 32

Javascript и часовые пояса — правильное время на сайте

JavaScript *
Sandbox
До сих пор существует путаница при реализации местного времени на сайте. Изрядный вклад в эту путаницу внесли российские законодатели с периодической отменой перехода на зимнее время. Вот Вы знаете какой сейчас у нас часовой пояс +3 или +4 часа? Вот и большинство пользователей этого не знают. Но есть очень простое решение как не отягощать пользователя этой проблемой! Нужно использовать время устройства (исходим из того, что это корректное местное время). Очевидное решение использовать функцию javascript getTimezoneOffset является в корне неправильным. Почему? Читайте дальше.
Читать дальше →
Total votes 23: ↑15 and ↓8 +7
Views 42K
Comments 28

Долгая история про локализацию даты без года в PHP

PHP *
Давайте начнём с простой задачки — вывести локализованную дату: там должен быть день, полное название месяца на языке локали и полный год. В наше время это действительно очень просто. В PHP есть своё i18n-расширение intl, которое входит в ядро с версии 5.3. И в этом intl есть класс IntlDateFormatter, у которого в свою очередь предопределено несколько форматов. Используем его LONG формат.

<?php

foreach (['en_US', 'ru_RU', 'es_ES', 'fa_IR'] as $locale) {
    $formatter = new IntlDateFormatter(
        $locale, 
        IntlDateFormatter::LONG, 
        IntlDateFormatter::NONE, 
        'Europe/Moscow'
    );
    echo $formatter->format(1455111783), PHP_EOL;
}

Результат:

February 10, 2016
10 февраля 2016 г.
10 de febrero de 2016
۱۰ ﻑﻭﺭیﻩٔ ۲۰۱۶ ﻡ. // вот тут вообще-то RTL-текст, но я хз как это правильно оформить

Пока неплохо. А теперь давайте слегка изменим условия: «вывести локализованную дату: там должен быть день и полное название месяца на языке локали». То есть, мы не хотим отображать год.
Казалось бы, ерунда. Но есть нюанс...
Total votes 37: ↑37 and ↓0 +37
Views 14K
Comments 40

Почему важно проверять значения возвращаемые функцией?

Python *Programming *
Sandbox

Мне очень захотелось поделиться опытом и я хотел бы поговорить о том, почему важно проверять значения возвращаемые функцией. В качестве примера возьмём python и ctypes. Некоторое время назад я столкнулся с достаточно интересным багом суть которого сводилась к тому, что при запуске скрипта на Linux-системе были неправильные данные, но не было трэйсбэка, а на Windows-системе сразу же получали трэйсбэк. Исследование кода показало, что виноваты были некорректные данные даты приходящие в функцию strptime(). Теперь, давайте, посмотрим на пример работы с функцией strptime() в питоне.

Читать дальше →
Total votes 30: ↑14 and ↓16 -2
Views 8.1K
Comments 15

Точность через неточность: Улучшаем Time-объекты

Website development *PHP *Programming *Designing and refactoring *
Translation
При создании value-объекта для хранения времени, я рекомендую выбирать вместе с экспертами в предметной области и вокруг нее с какой точностью он будет храниться.

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


К сожалению, так делают не часто, и, когда приходит момент, проблема дает о себе знать. Рассмотрим следующий код:


$estimatedDeliveryDate = new DateTimeImmutable('2017-06-21');

// представим, что сегодня ТАКЖЕ 2017-06-21
$now = new DateTimeImmutable('now');

if ($now > $estimatedDeliveryDate) {
    echo 'Package is late!';
} else {
    echo 'Package is on the way.';
}

Ожидаемо что, что 21 июня этот код выведет Package is on the way., ведь день еще не закончился и пакет, например, доставят ближе к вечеру.


Несмотря на это код так не делает. Так как не указана часть со временем, PHP заботливо подставляет нулевые значения и приводит $estimatedDeliveryDate к 2017-06-21 00:00:00.
С другой стороны $now вычисляется как… сейчас. Now включает в себя текущий момент времени, который, скорее всего, не полночь, так что получится 2017-06-21 15:33:34 или вроде того, что будет позднее, чем 2017-06-21 00:00:00.

Читать дальше →
Total votes 13: ↑13 and ↓0 +13
Views 4.5K
Comments 25

Кастомная (де) сериализация даты и времени в Spring

Java *
Sandbox

Представьте довольно распространённую ситуацию: ваше приложение взаимодействует с клиентами, которые находятся в разных часовых поясах. Вам часто приходится работать с датами, а для корректной работы системы, они передаются с указанием часового пояса отправителя. При этом, вам нужно:

1)      При получении запроса привести дату к серверному времени и сохранить в базу данных в таком виде

2)      В ответ возвращать дату и время с указанием серверного часового пояса

Чтобы избавиться от лишних вызовов методов для преобразования даты, Spring предоставляет удобный механизм для написания кастомной сериализации и десериализации.

Читать далее
Total votes 9: ↑8 and ↓1 +7
Views 4.1K
Comments 6
1