Есть ли стандарт для инклюзивных / эксклюзивных концов временных интервалов? - PullRequest
39 голосов
/ 21 марта 2012

Мне интересно, существует ли стандартный или "нормальный" способ интерпретации конечных точек данных временного интервала в отношении инклюзивности / исключительности значения, определяющего конечную точку. Тем не менее, обратите внимание, что я спрашиваю, что такое стандартное (или наиболее распространенное) соглашение (если оно есть), а не для диссертации о ваших личных предпочтениях. Если вы действительно хотите представить диссертацию, пожалуйста, приложите ее к ссылке на чей-то опубликованный стандарт или стандартный текст по данному вопросу. Открытые стандарты (которые мне не нужно платить за чтение) очень предпочтительны, если они не имеют принципиальных недостатков:).

Конечно, есть 4 возможности для временного интервала от А до В:

  1. (A, B) - оба конца являются эксклюзивными.
  2. [A, B] - оба конца включительно.
  3. [A, B) - начало включительно, а конец - исключительно
  4. (A, B] - начало эксклюзивное, а конец включительно

У каждого из них свои характеристики (как я понимаю, не стесняйтесь указывать больше)

Соглашение [A, B] будет иметь кажущееся неудобным свойство, заключающееся в том, что B содержится внутри целого числа [A, B], а также [B, C]. Это особенно неудобно, если B предназначено для представления границы полуночи, и вы пытаетесь определить, на какой день он выпадает, например. Кроме того, это означает, что длительность интервала немного раздражает для вычисления, поскольку [A, B], где A = B должна иметь длину 1, и, следовательно, продолжительность [A, B] равна (B - A) + 1

Точно так же (A, B) конвенция столкнулась бы с трудностью того, что B не попадает ни в (A, B), ни в (B, C) ... продолжая аналогию с дневными границами, полночь не будет частью ни дня. Это также логически неудобно, потому что [A, B], где A = B - это бессмысленный интервал с продолжительностью меньше нуля, , но изменение A и B не делает его действительным интервалом .

Поэтому я думаю, что хочу либо [A, B), либо (A, B], и я не могу понять, как сделать выбор между ними.

Так что, если у кого-то есть ссылка на стандартный документ, ссылка на стандартный текст или аналогичный, который разъясняет соглашение, было бы замечательно. С другой стороны, если вы можете связать множество стандартных документов и / или ссылок, которые более или менее полностью не согласны, то я могу просто выбрать тот, который, кажется, имеет достаточные полномочия для CMA, и с этим можно покончить :).

Наконец, я буду работать на Java, поэтому я особенно восприимчив к ответам, которые хорошо работают на Java.

Ответы [ 6 ]

46 голосов
/ 21 марта 2012

В общем случае у [A, B) есть много чего, и я не вижу причин, по которым это не будет верно для временных интервалов.

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

Краткое изложение преимуществ:

  • end - start равно количеству элементов в списке
  • верхняя граница предыдущего интервала является нижней границей следующего
  • позволяет индексировать интервал, начинающийся с 0, без знака [1]

Лично второй пункт чрезвычайно полезен для множества проблем; рассмотрим довольно стандартную рекурсивную функцию (в псевдо-питоне):

def foo(start, end):
    if end - start == 1:
        # base case
    else:
        middle = start + (end - start) / 2
        foo(start, middle)
        foo(middle, end)

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

[1] Это преимущество по сравнению с (A, B] - интервал, начинающийся с 0, НАМНОГО более распространен, чем интервал, заканчивающийся в MAX_VAL. Обратите внимание, что это также относится к одной дополнительной проблеме: использование двух включающих границ означает, что мы можем обозначить последовательность, длина которой не может быть выражена одинаковым размером.

5 голосов
/ 21 марта 2012

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

Временные интервалы в наших приложениях будут представлены в виде пары мгновенных моментов с условием, что время начала является включающим, а время окончания - исключительным.Это соглашение математически удобно в том смысле, что разность границ равна длине интервала, а также численно согласуется с тем, как массивы и списки подписываются в Java-программах (см. http://www.cs.utexas.edu/~EWD/ewd08xx/EWD831.PDF). Практический результат этогоэтот интервал 2012-03-17T00: 00: 00.000Z - 2012-03-18T00: 00: 00.000Z обозначает весь день Святого Патрика, и каждая дата, начинающаяся с 2012-03-17, будет определяться как включенная в StДень Патрика, но 2012-03-18T00: 00: 00.000Z не будет включен, а День Святого Патрика будет включать ровно 24 * 60 * 60 * 1000 миллисекунд.

2 голосов
/ 03 августа 2017

java.time & Half-Open

java.time классы, которые заменяют проблемные унаследованные классы даты и времени, а также проект Joda-Time определяют промежуток времени, используя подход Half-Open [), где начало включительно , в то время как окончание исключительно .

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

Я пришел к выводу о преимуществах использования этого подхода последовательно во всем моем коде обработки даты и времени. Например, неделя, начинающаяся с понедельника, заканчивается, но не включает следующий понедельник. Месяц начинается 1-го числа и длится до первого числа следующего месяца, но не включает в себя, таким образом, игнорируется задача определения номера последнего дня месяца, включая високосный год 28/29 февраля.

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

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

Кстати, обратите внимание, что Half-Open [) означает избегать соединения SQL BETWEEN, поскольку оно всегда полностью закрыто [].

Что касается делового мышления клиентов, которых я обслуживаю, там, где это уместно, я стараюсь убедить их также постоянно использовать Half-Open. Я видел много ситуаций, когда различные бизнесмены делали неверные предположения относительно периодов времени, указанных в отчетах. Последовательное использование Half-Open позволяет избежать этих неприятных неясностей. Но если клиент настаивает, я отмечаю это в своем коде и настраиваю входы / выходы так, чтобы использовать Half-Open в моей собственной логике. Например, моя логика использует неделю с понедельника по понедельник, но в отчете вычтите день, чтобы показать воскресенье.

Еще больше классов, представляющих промежутки времени с подходом Half-Open [), см. В проекте ThreeTen-Extras для его класса Interval (пара объектов Instant) и LocalDateRange класс (пара объектов LocalDate).


О java.time

Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют старые классные устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Где взять классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

2 голосов
/ 02 августа 2017

Несмотря на то, что этот поток фокусируется больше на Java, я подумал, что было бы весьма интересно увидеть другие принятые соглашения, особенно учитывая, что библиотека pandas Python в настоящее время повсеместно используется для анализа данных, иТот факт, что эта страница StackOverflow является одним из лучших результатов поиска при поиске соглашений об включенности / исключительности временных диапазонов.

Цитирование этой страницы :

Даты начала и окончания строго указаны.Таким образом, он не будет генерировать какие-либо даты вне этих дат, если они указаны.

Кроме того, это не только генерация диапазонов дат.Соглашение также принимается при попытке индексации данных временных рядов.Вот простой тест для фреймов данных с DatetimeIndex

>>> import pandas as pd
>>> pd.__version__
'0.20.2'
>>> df = pd.DataFrame(list(range(20)))
>>> df.index = pd.date_range(start="2017-07-01", periods=20)
>>> df["2017-07-01":"2017-07-05"]
            0
2017-07-01  0
2017-07-02  1
2017-07-03  2
2017-07-04  3
2017-07-05  4
2 голосов
/ 21 марта 2012

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

Что касается того, что поддерживается в Java, библиотека Joda Time реализует Interval с, которые включают время начала, но не время окончания

1 голос
/ 03 ноября 2017

Я только что прошел тот же самый мыслительный процесс, и я думаю, что очень важно, чтобы это было как-то стандартизировано или, по крайней мере, разъяснено с помощью этих типов сообщений Q & A!

В нашем случаерассматриваемые диапазоны дат используются в качестве входных и выходных данных для / от микросервиса;тот, который, по крайней мере в краткосрочной перспективе, будет вызван существующим монолитным приложением (это проект разложения монолита).Поэтому я думаю, что приведенный выше комментарий, касающийся решения, основанного на бизнес-требованиях, в нашем случае менее актуален (поскольку «1003 * прямые « пользователи »создаваемого нами программного обеспечения - действительно технические люди),Если бы мы обрабатывали ввод от выбора даты, это могла бы быть другая история!

Моя рекомендация состояла в том, чтобы все даты начала включались, а все даты окончания были эксклюзивными - поэтому [A, B) в вашей записи.Это было сделано по следующим причинам:

  1. Ранее мы договорились, что любые входящие даты, содержащие части времени, будут отклонены (даже если значение JSON было "2018-01-01T00: 00: 00") и что мы будем выводить все даты без времени.Поэтому, если дата окончания является исключительной, как только строка будет десериализована в объект .NET DateTime, это будет выходной.

  2. Мне нравится идея, что диапазон дат (который в нашем случае всегда должен давать целые дни) всегда можно рассчитать, просто выполнив dateRange = (endDateExcl - startDateIncl) .TotalDays.Не нужно добавлять 1 везде!

  3. Большая часть бизнес-проверки, выполняемой службой, проверяет, что несколько диапазонов данных находятся на одном уровне друг с другом без пропусков.Это легко проверить при использовании [A, B), потому что каждый B должен соответствовать предыдущему A. Если мы пойдем с [A, B], то мы (разработчики, тестировщики, инженеры поддержки) часто спрашиваем себя: «Сколько днейснова в марте?(например, [2018-03-01,2018-03-30], [2018-04-01,2018-04-30]) или «Есть ли в 2016 году високосный день?»(например, [2016-02-01,2016-02-28], [2016-03-01,2016-03-30]).

Просто добавьте, я настоятельно рекомендуюкто угодно, независимо от решения, явно суффиксировать все имена атрибутов, переменных, методов или иным образом с помощью «Incl» или «Excl», чтобы всем было понятно без поиска документации!

Мы также порекомендоваличто все даты должны быть представлены в формате ISO и что все, что имеет «Z» в конце, также должно быть отклонено (поскольку понимание состоит в том, что мы работаем целыми днями, и мы не хотим, чтобы дата была десериализована вОбъект DateTime с часом-изгоем (или 23!) Из-за перехода на летнее время).

Сноска, я, вероятно, разместил бы это в качестве комментария к ответу Во, но я только (запоздало!) Присоединился к SO и должен заработать свое признание, прежде чем я смогу это сделать!; -)

счастливых знакомств x

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