Я столкнулся с странным timewarp, выполняя некоторую математику со временем, и это оставило меня в тупике. Или, ну, я нашел причину (или, по крайней мере, правдоподобную), но не знаю, что с этим делать, или если есть что-то, что можно сделать.Проблемы с добавлением времени
Проблема в простых словах заключается в том, что при добавлении времени в более крупных единицах, чем за 1 неделю (исключая множители), представляется невозможным быть точным. И, точнее, я имею в виду, что когда я добавляю 1 год в секунду, чтобы СЕЙЧАС, я получаю 1 год и несколько часов от СЕЙЧАС.
Я могу понять, что добавление 1 (или более) месяцев будет делать это, так как длина месяца варьируется, но год должен быть более или менее одинаковым, не так ли?
Теперь я знаю, что вы хотите знать, как я это делаю, так что здесь следует (pseudoish) Код:
class My_DateInterval {
public $length; // Interval length in seconds
public function __construct($interval) {
$this->length = 0;
preg_match(
'/P(((?<years>([0-9]{1,}))Y)|((?<months>([0-9]{1,}))M)|((?<weeks>([0-9]{1,}))W)|((?<days>([0-9]{1,}))D)){0,}(T((?<hours>([0-9]{1,2})){1}H){0,1}((?<minutes>([0-9]{1,2}){1})M){0,1}((?<seconds>([0-9]{1,2}){1})S){0,1}){0,1}/',
$interval, $timeparts
);
if (is_numeric($timeparts['years'])) $this->length += intval($timeparts['years']) * 31556926; // 1 year in seconds
if (is_numeric($timeparts['months'])) $this->length += intval($timeparts['months']) * 2629743.83; // 1 month in seconds
if (is_numeric($timeparts['weeks'])) $this->length += intval($timeparts['weeks']) * 604800; // 1 week in seconds
if (is_numeric($timeparts['days'])) $this->length += intval($timeparts['days']) * 86400; // 1 day in seconds
if (is_numeric($timeparts['hours'])) $this->length += intval($timeparts['hours']) * 3600; // 1 hour in seconds
if (is_numeric($timeparts['minutes'])) $this->length += intval($timeparts['minutes']) * 60; // 1 minute in seconds
if (is_numeric($timeparts['seconds'])) $this->length += intval($timeparts['seconds']);
$this->length = round($this->length);
}
}
class My_DateTime extends DateTime {
public function __construct($time, $tz = null) {
parent::__contruct($time, $tz);
}
public function add(My_DateInterval $i) {
$this->modify($i->length . ' seconds');
}
}
$d = new My_DateTime();
$i = new My_DateInterval('P1Y');
$d->add($i);
Выполнение некоторых отладочных распечаток длины интервала и до/после значения показывают, что все это хорошо, в том смысле, что «он работает так, как ожидалось, и все проверяет», но проблема, о которой говорилось выше, все еще стоит: есть аномалия в точности всего этого, что я бы очень хотел получить, если это возможно.
Во многих словах: как сделать точную математику с единицами времени более 1 недели. (I.e. 1 месяц/1 год).
PS. Для тех, кто задается вопросом, почему я использую классы My_ *, так это потому, что PHP 5.3 просто недостаточно распространен, но я пытаюсь сохранить что-то таким образом, что переход на встроенные классы полезности будет максимально гладким.
Да, это в значительной степени то, что я подозревал. Я полагаю, что для этого могут быть библиотеки, но мне они действительно не нужны, мне просто нужно пересмотреть мой подход. Спасибо! –