LINUX.ORG.RU

Вычисления с датами


0

1

Чем можно складывать и вычитать даты?

«2011.12.31 + 1 = 2012.01.01», «2012.01.01 - 2011.12.31 = 1» и тд.

Нужен какой-нибудь калькулятор или язык, в котором это просто делается.

★★

boost date_time для C++

date d(2005, Nov, 30); // last day of November
d + months(1); // result is last day of December "2005-Dec-31"
d - months(1); // result is last day of October "2005-Oct-31"

CEMEH
()

Очевидно, перевести их в unixtime или в юлианские даты (смотря насколько у вас эти даты будут разбросаны).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

read about calendars, chronology, leap seconds, timezone, etc.

we don't know in far future how calendars will change, for some locations we don't know how calendar is or was

anonymous
()

python

«2011.12.31 + 1 = 2012.01.01»
«2012.01.01 - 2011.12.31 = 1»

>>> from datetime import datetime, timedelta
>>> print datetime.__doc__
datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
>>> datetime(2011, 12, 31) + timedelta(days=1)
datetime.datetime(2012, 1, 1, 0, 0)
>>> datetime(2012, 1, 1) - datetime(2011, 12, 31)
datetime.timedelta(1)

redixin ★★★★
()
Ответ на: комментарий от adriano32

>Перевести в unix epoch time, прибавить 24*3600

Два раза в год получишь смещение на час и раз в пару лет - сдвиг на секунду. Где-то, конечно, не критично, но помнить нужно.

Лучше strtotime(«+1 day») и т.п.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Однозначно вы правы, но тогда перенести топик в девелопмент. «язык, в котором это просто делается.» как бы намекает на познания ТС в ЯП.

adriano32 ★★★
()
Ответ на: комментарий от anonymous

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: python от redixin

Питон хорош. Похоже, лучшее из предложенного.

fffgh ★★
() автор топика
Ответ на: комментарий от KRoN73

>> Перевести в unix epoch time, прибавить 24*3600

Два раза в год получишь ...

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

Лучше strtotime(«+1 day») и т.п.

Это из php, да? Хорошая вещь, как и вышеупомянутая date, в питоне бы такую.

Но как считать разность между датами? Тут http://php.net/manual/en/function.strtotime.php предлагают как раз самому делить на 86400, что, по идее, и приведёт к

смещение на час и раз в пару лет - сдвиг на секунду.

fffgh ★★
() автор топика
Ответ на: комментарий от fffgh

Речь, как я понял, о разности между датами

Тем более. В лоб не пересчитывается.

Это из php, да?

Не только. В какой-то либе на Си я её видел, ЕМНИП.

Но как считать разность между датами?

Если именно разность - то приведением к независимой системе счисления. Или unixtime, или jdate. И расчётом разницы. Проще, ИМХО, - через unixtime считать. Потому что универсальная абсолютная шкала. Голова должна болеть только при приведении к ней текущей даты и обратно.

предлагают как раз самому делить на 86400

В общем случае будет ошибка, так как не в каждых сутках по 86400 секунд.

Вообще, вот опорные точки для тестов.

30.10.2010 22:00 MSK = 1288461600 Если прибавить 86400 секунд, то получим 1288548000 = Sun, 31 Oct 2010 21:00:00 +0300

Вопрос, что нам требуется получить.

$ php -r '$d1 = new DateTime("31.10.2010 21:00"); $d2 = new DateTime("30.10.2010 22:00"); $diff = $d2->diff($d1); echo $diff->format("%d days %h hours");'
0 days 23 hours

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> 30.10.2010 22:00 MSK = 1288461600

Если прибавить 86400 секунд, то получим 1288548000 = Sun, 31 Oct 2010 21:00:00 +0300



php > echo strtotime(«2010-11-01»)-strtotime(«2010-10-31»);
90000

php > echo strtotime(«2010-03-29»)-strtotime(«2010-03-28»);
82800

В общем, питон рулит.

fffgh ★★
() автор топика
Ответ на: комментарий от fffgh

>php > echo strtotime(«2010-11-01»)-strtotime(«2010-10-31»);

90000


А что не нравится? Всё правильно, 86400+3600 = 90000. 31-го числа в сутках было 90000 секунд.

82800


86400-3600 - 82800. И тут всё верно. В сутках было на час меньше.

В общем, питон рулит.


В Питоне другой календарь, что ли? :D Для другой планеты?

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Всё правильно

Не сомневаюсь, что правильно. Проиллюстрировал, как это выглядит.

В Питоне другой календарь, что ли?


Там можно посчитать разницу в днях, а не секундах.

date(2010,11,01)-date(2010,10,31)

datetime.timedelta(1)

date(2010,03,29)-date(2010,03,28)

datetime.timedelta(1)

fffgh ★★
() автор топика
Ответ на: комментарий от KRoN73

По-моему разница между

Если именно разность - то приведением к независимой системе счисления. Или unixtime, или jdate. И расчётом разницы. Проще, ИМХО, - через unixtime считать. Потому что универсальная абсолютная шкала. Голова должна болеть только при приведении к ней текущей даты и обратно.

и

date(2010,11,01)-date(2010,10,31)

очевидна.

fffgh ★★
() автор топика
Ответ на: комментарий от fffgh

>date(2010,11,01)

А полный формат с таймзоной как будет записан?

очевидна


Чем же очевидна разница, если по сути это одно и то же?

KRoN73 ★★★★★
()
Ответ на: комментарий от fffgh

Это из php, да? Хорошая вещь, как и вышеупомянутая date, в питоне бы такую.

>>> from datetime import datetime, timedelta
>>> datetime.now() + timedelta(days=1, hours=2)
datetime.datetime(2011, 2, 18, 12, 0, 7, 509713)
redixin ★★★★
()
Ответ на: комментарий от redixin

И да

>>> (datetime.now() + timedelta(days=1, hours=2)).strftime("%c")
'Fri Feb 18 12:02:50 2011'
redixin ★★★★
()
Ответ на: комментарий от KRoN73

> А полный формат с таймзоной как будет записан?

Я с датами работаю, мне полный формат не нужен.

Но вообще - работает и с часами/минутами:

datetime(2010,11,01,21,15)-datetime(2010,10,30,21,15)

datetime.timedelta(2)

Чем же очевидна разница, если по сути это одно и то же?


Можно хотя бы знаки пересчитать.

fffgh ★★
() автор топика
Ответ на: комментарий от redixin

Та функция понимает строки в самых разных форматах. Вот несколько примеров:

<?php
echo strtotime(«now»), «\n»;
echo strtotime(«10 September 2000»), «\n»;
echo strtotime(«+1 day»), «\n»;
echo strtotime(«+1 week»), «\n»;
echo strtotime(«+1 week 2 days 4 hours 2 seconds»), «\n»;
echo strtotime(«next Thursday»), «\n»;
echo strtotime(«last Monday»), «\n»;
?>

Встроенное сложение даты и числа, опять же. Суть в этом, в «интуитивно понятном» использовании.

В питоне на неё похожа datetime.strptime(), но она не такая мощная, да и формат данных надо указывать самому.

fffgh ★★
() автор топика
Ответ на: комментарий от fffgh

>Но вообще - работает и с часами/минутами

Я же про таймзону спросил.

Кстати:

datetime(2010,11,01,0,0)-datetime(2010,10,31,0,0)

datetime.timedelta(1)


Почему timedelta = ровно 1 день? Ведь 25 часов.

KRoN73 ★★★★★
()
Ответ на: комментарий от marvin_yorke

>зачем в date (не datetime) таймзона?

Чтобы знать, где разница будет 24 часа, а где - 25 часов.

KRoN73 ★★★★★
()
Ответ на: комментарий от fffgh

> Суть в этом, в «интуитивно понятном» использовании.

Меня всегда пугала эта магия

redixin ★★★★
()
Ответ на: комментарий от redixin

>Чегойто вдруг?

Потому что между 00:00 31 октября 2010-го года и 00:00 1 ноября 2010-го года было 25 часов разницы.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Потому что между 00:00 31 октября 2010-го года и 00:00 1 ноября 2010-го года было 25 часов разницы.

ну это смотря где

redixin ★★★★
()
Ответ на: комментарий от redixin

>ну это смотря где

1. Мы тут про вполне конкретную Россию.

2. Вот потому я выше спрашивал про таймзоны.

KRoN73 ★★★★★
()
Ответ на: комментарий от redixin

>А вообще както все печально с таймзонами.

Если при вводе даты сразу переводить её в UNIXTIME, хранить и обрабатывать в UNIXTIME и только при выводе приводить в текущую локаль - то всё замечательно, никаких нареканий.

Кстати, в MySQL поэтому тоже дата ни в коем случае ни в DATETIME, а или в TIMESTAMP или в INT.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Если при вводе даты сразу переводить её в UNIXTIME, хранить и обрабатывать в UNIXTIME и только при выводе приводить в текущую локаль

В этом то и печаль

redixin ★★★★
()
Ответ на: комментарий от KRoN73

>Если при вводе даты сразу переводить её в UNIXTIME, хранить и обрабатывать в UNIXTIME и только при выводе приводить в текущую локаль - то всё замечательно, никаких нареканий.

Отлично, у тебя по филиалу в каждом часовом поясе, надо получить суммарный отчёт отчёт за сутки, которые в каждом часовом поясе «свои по UNIXTIME». Простым а-ля «SQL-запросом» ты уже ни как не отделаешься...

yyk ★★★★★
()
Ответ на: комментарий от Eddy_Em

>А если дата до 1970 года?

Да хоть до рождества Христова. Отрицательные целые уже забанили? :D

$ php -r 'echo strtotime(«01.01.0001»);'
-62135605800

Вот -1-й год (Христос же, вроде, 25.12.-1 родился?) не сожрёт, тут уже нужно mktime использовать :)

$ php -r 'echo mktime(0,0,0,12,25,-1);'
-62167833000

KRoN73 ★★★★★
()
Ответ на: комментарий от yyk

>Отлично, у тебя по филиалу в каждом часовом поясе, надо получить суммарный отчёт отчёт за сутки, которые в каждом часовом поясе «свои по UNIXTIME»

Ну так прекрасно, для каждого филиала и получишь отчёт. В чём проблема-то?

Простым а-ля «SQL-запросом» ты уже ни как не отделаешься...


Поясни сперва, что непонятно. Если набор данных за интервал абсолютного времени - то местные часовые пояса не у дел. Если за сутки в конкретных таймзонах - то обобщать нельзя, хотя бы потому, что у тебя длительность этих суток в разных таймзонах в общем случае может быть разной.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

>Ну так прекрасно, для каждого филиала и получишь отчёт. В чём проблема-то?

Ни в чём - нашли проблему на ровном месте. Решили одно - вылезло другое. Я о том что «Если при вводе даты сразу переводить её в UNIXTIME... - то всё замечательно, никаких нареканий.» без уточнения условий попахивает абсолютизмом...

Если за сутки в конкретных таймзонах - то обобщать нельзя


опять этот надоедливый запах... Не надоело строить заборы?

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


Это отменяет понятия «суток», «календарных дней» и проч.?

yyk ★★★★★
()
Ответ на: комментарий от KRoN73

-62167833000

Это чего за тип такой? u_int_64t?

И, кстати, ваш пыхпых при переводе дат учитывает летнее/зимнее время, а также эпохи смены календарей?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от yyk

>без уточнения условий попахивает абсолютизмом

А это и есть абсолютизм. По определению абсолютного времени :D Единственный вариант не иметь проблем с преобразованиями в будущем.

опять этот надоедливый запах... Не надоело строить заборы?


Это аргументация такая?

Это отменяет понятия «суток», «календарных дней» и проч.?


Нет. Но эти понятия не строгие и об этом нужно помнить.

KRoN73 ★★★★★
()
Ответ на: комментарий от Eddy_Em

>u_int_64t?

u с минусом - это сильно :) Обычный int64.

И, кстати, ваш пыхпых при переводе дат учитывает летнее/зимнее время


Какую таймзону укажешь - то и получишь. Как и всюду. Более того, не думаю, что PHP этот зоопарк в себе таскает, скорее всего системными либами пользуется.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

>А это и есть абсолютизм. По определению абсолютного времени :D Единственный вариант не иметь проблем с преобразованиями в будущем.

Преждевременная оптимизация? :)

Это аргументация такая?


Нет, чистой воды недоумение: для принятия удобного нам решения оградим поле возможных вариантов кучей «нельзя» и сидим с довольным видом - как круто мы «вписались» в нами же выстроенные «рамки»

Но эти понятия не строгие и об этом нужно помнить.


Об этом и помнят. Но хотят оперировать вот этими «нестрогими понятиями».

yyk ★★★★★
()
Ответ на: комментарий от yyk

>Преждевременная оптимизация? :)

Нет, реальная практика :)

Нет, чистой воды недоумение


Мне непонятно это недоумение. Ну да, нельзя совать пальцы в розетку или кушать протухшую еду, некрасиво пукать и ковыряться в носу. Это всё - ограждения, да? Ну, слава Богу, мне с Вами тогда не по пути :D

Об этом и помнят.


По этой теме не похоже.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Почему timedelta = ровно 1 день? Ведь 25 часов.

Ну так день ведь прошёл. Мало ли сколько в нём часов.

Хотя, возможно, дело в том, что там не учитывают перевод часов в России:

datetime(2010,10,31,4)-datetime(2010,10,31,1)

datetime.timedelta(0, 10800)

php > echo strtotime(«2010-10-31 04:00»)-strtotime(«2010-10-31 01:00»);
14400

Вообще интересно с этим переводом.

31 октября 2010 02:01 было дважды, до и после перевода. Как отличают один момент от другого? Ерунда получается:

php > echo strtotime(«2010-10-31 01:01 + 1 hour»);
1288465260

php > echo strtotime(«2010-10-31 01:01») + 3600;
1288461660

Плюс - вопрос о последних достижениях России в области учёта времени:

php > echo strtotime(«2011-10-30 04:00»)-strtotime(«2011-10-30 01:00»);
14400

А ведь, говорят, в октябре 2011 переводить уже не будут. Ошибка, то есть.

fffgh ★★
() автор топика
Ответ на: комментарий от KRoN73

>Нет, реальная практика :)

перестаньте натягивать кое-что на глобус :)

Мне непонятно это недоумение... мне с Вами тогда не по пути


Да на здоровье... Грустно мне, то вы так гордитесь своими «заборами», и даже мыслей не допускаете, что «за забором» что-то может быть [полезное]...

yyk ★★★★★
()
Ответ на: комментарий от fffgh

>31 октября 2010 02:01 было дважды, до и после перевода. Как отличают один момент от другого?

В php-шной mktime есть параметр $is_dst, который указывает явно, летнее ли это время. В strtotime() упоминается модификатор DST/noDST, только с первой попытки у меня что с ним, что без него время совпадает, если понадобится - нужно глубже копать :)

А ведь, говорят, в октябре 2011 переводить уже не будут. Ошибка, то есть.


sys-libs/timezone-data ещё не обновлялся на эту тему, видимо. Ждём 2011c :)

KRoN73 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.