Является ли TimeSpan ненужным? - PullRequest
       18

Является ли TimeSpan ненужным?

17 голосов
/ 19 сентября 2009

РЕДАКТИРОВАТЬ 2009-Nov-04

Хорошо, прошло немного времени с тех пор, как я впервые опубликовал этот вопрос. Мне кажется, что многие из первых респондентов не смогли по-настоящему понять то, что я говорил - общим ответом было какое-то изменение «То, что вы говорите, не имеет никакого смысла» - и поэтому я сделал несколько полезных диаграммы, которые действительно иллюстрируют мою точку зрения.

Когда мы говорим о числах, мы обычно имеем в виду пункты о том, что дети начальных классов изучают, называется Числовой линией:

The number line

Теперь, когда мы изучаем арифметику, наши умы учатся выполнять очень интересные преобразования этой концепции. Например, для оценки выражения 1 + 0.5, если бы мы просто применили наше «мышление числовой линии», нам бы потребовалось как-то разобраться в этом:

Adding two points on the number line

Трудно действительно проиллюстрировать это, потому что трудно подумать об этом: «добавление» двух пунктов. Именно здесь многие респонденты боролись с идеей добавления дат (или просто отклонили это как абсурдное), потому что они думали о датах как о точках.

Однако выражение 1 + 0.5 действительно имеет для нас смысл, потому что, когда мы думаем об этом, мы действительно воображаем это:

Adding a number (point) and a magnitude (vector)

То есть число (или точка ) 1 плюс вектор 0,5, в результате чего точка 1,5.

С другой стороны, мы можем представить себе это:

Adding two vectors

То есть вектор 1 плюс вектор 0,5, что приводит к вектору 1,5.

Другими словами, когда мы имеем дело с числами, мы рассматриваем точки и векторы взаимозаменяемо. Но как насчет дат? Даты, в конце концов, в основном числа. Если вы мне не верите, сравните эту строку с числовой строкой выше:

A timeline

Заметили соответствие между временной шкалой и числовой линией? Это была моя точка зрения: если мы выполним преобразование выше с числами , мы должны быть в состоянии сделать это и с датами. Таким образом, применяя «мышление по временной шкале», выражение 0001-Jan-02 00:00:00 + 0001-Jan-01 12:00:00 не имеет большого смысла, как отметили многие респонденты:

Adding two points on a timeline

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

Adding a point in time and a time vector

Очевидно, что разница между DateTime и TimeSpan - это та же разница, которая существует между точкой и вектором. Я думаю, что многие люди негативно отреагировали на моё предположение о том, что просто так неестественно думать о датах как о величинах таким образом. Но я не согласен с аргументом о том, что нет очевидного ориентира для использования в качестве нуля. Существует очевидный ориентир, и я дам вам подсказку, где он находится: около 2010 года назад.

Не поймите меня неправильно: я не подвергаю сомнению полезность в проведении концептуального разрыва между понятиями DateTime и TimeSpan. Действительно, мой вопрос должен был быть (как косвенно предложил ChrisW), почему do мы рассматриваем числа и векторы взаимозаменяемо при работе с обычными числовыми типами? (Или: почему у нас только один тип int вместо int и intspan?) Есть большая разница, и все же мы никогда не думаем об этом, пока в какой-то средней или старшей школе, когда мы начинаем геометрию. И затем это воспринимается как новая математическая концепция, когда в действительности это то, что мы используем с тех пор, как научились добавлять числа, считая их пальцами.

В конце концов, лучший ответ пришел от Strilanc, который указал, что использование DateTime и TimeSpan действительно является реализацией аффинного пространства , которое имеет удобное свойство не нуждающихся в контрольную точку, чтобы рассматривать в качестве начала координат. Так что спасибо, Стриланк. Тем не менее, я даю признанный ответ ChrisW за то, что был первым, кто поднял концепцию векторов и точек, которая действительно добралась до сути вопроса.


ОРИГИНАЛЬНЫЙ ВОПРОС (для потомков)

Я, конечно, не умею программировать на все руки, но я знаю, что и PHP, и .NET имеют класс TimeSpan в дополнение к классу DateTime (или структуре в .NET), и я предполагаю, что это случай в различных других языках и фреймворках, а также (хотя я пишу это в первую очередь со ссылкой на структуры .NET). Это может показаться странным вопросом, но не является ли TimeSpan избыточным?

Если вы считаете, что ответ очевиден («A DateTime - абсолютный момент времени, а TimeSpan - интервал времени - такой простой!»), Учтите следующее: целое число может быть концептуализируется как абсолютное значение (точка на числовой линии) или как расстояние между значениями - и нам не нужны два отдельных типа данных для этих различных концептуализаций. Я все еще могу написать 5 + 6 без какой-либо двусмысленности относительно того, что я имею в виду.

До тех пор, пока существует постоянная ссылка на нулевую точку, мне кажется, не должно быть никаких причин, по которым нужен объект TimeSpan для выполнения арифметических операций над DateTime объектами или для получения расстояния между ними .

Что мне не хватает? Почему уникальные методы и свойства структуры TimeSpan нельзя просто сложить в DateTime?

(Отказ от ответственности: не похоже, что я увлечен этим или чем-то еще; я в порядке, используя DateTime и TimeSpan объекты, как они предназначены все время. Я просто задаю вопрос. )

РЕДАКТИРОВАТЬ : Хорошо, упрощенный пример, иллюстрирующий мою точку зрения:

Рассмотрим уравнение 10 - 5 = 5. Можно было бы прочитать это как «Начните с 10 (значение), сдвиньте 5 влево (интервал), и вы в итоге получите 5 (значение).»

Предположим, просто чтобы упростить задачу, мы допустим, что 1 января 1900 года будет точка ноль, и мы определим TimeSpan объекты только в днях.

Тогда 10 - 5 = 5 можно было бы понимать в терминах DateTime как 11 января 1900 г. - 6 января 1900 г. = 6 января 1900 г. Это хорошо, потому что 11 января - это просто "10" по нашему определению и 6 января "5" . Тот факт, что мы рассматриваем 10 как значение , первые 5 как span , а последние 5 как значение снова, просто для нашего собственного концептуальная выгода. Суть в том, что единственное различие заключается в том, как вы думаете о числе, а не в том, как оно есть на самом деле. Вот почему у нас нет отдельных структур, скажем, для целочисленных значений и целых интервалов - простое старое целое число охватывает все наши базы.

Имею ли я какой-то смысл?

Ответы [ 10 ]

18 голосов
/ 19 сентября 2009

Дата не ведет себя как целое число, я не могу вспомнить классификацию алгебры, но учтите это:

Date + Span = Date
Date - Date = Span  
Date + Date = undefined

Span + Span = Span
Span - Span = Span

За любой данный год,

10 feb + 10 days = 20 feb
20 feb - 20 jan  = 31 days
20 jan + 20 feb  = ???

Это последнее вычисление может быть интерпретировано как значимое, когда мы рассматриваем дату как число дней с даты начала. Но значение будет таким же произвольным, как и значение StartDate.

12 голосов
/ 19 сентября 2009

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

По вашей логике, это не TimeSpan, что не нужно: скорее, это DateTime, которое не нужно, и может быть заменено на TimeSpan (длительность с нуля).

Плюс есть тот факт, что целые числа имеют очевидный ноль, тогда как Даты, однако, не имеют явного нуля; но наличие очевидного нуля необходимо, если вы хотите заменить «место на числовой линии» на «расстояние / расстояние от нуля / начало».


Edit:

Точка (местоположение на плоскости) отличается от вектора.

Они кажутся похожими ...

  • Вектор (расстояние от начала координат) может представлять точку
  • Точка (относительно начала координат) может представлять вектор

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

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

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

[Заменить 'point' на DateTime, а 'vector' на TimeSpan в приведенном выше аргументе.]

Я думаю, что есть подлинная разница между абсолютными и относительными значениями. Я не знаю, почему это различие не является более очевидным в арифметике, то есть почему «числа» используются, по-видимому, взаимозаменяемо для представления как абсолютных, так и относительных значений.

12 голосов
/ 19 сентября 2009

(выступая в качестве математика) Это потому, что арифметические операции с «датой» не являются закрытыми или четко определены, что требует необходимости в дополнительной структуре.

Например, 1 января 2000 г. - 1 декабря 1999 г. = ...? Мы знаем, что между ними 31 день, но если это было истолковано как дата, то ответ - Эпоха (то есть ноль) + 31 день. Это больше не является действительной «датой».

Точно так же все арифметические операции над целыми числами определены недостаточно (1/2 не имеет ответа в целых числах. Здесь целочисленная математика возвращает ноль, но 0 * 2 = 0, а не 1, как вы ожидаете). Это вызывает необходимость в дополнительной структуре, которую мы называем дробями.

5 голосов
/ 20 сентября 2009

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

Различие между временным интервалом и датой сводится к сложению. Имеет смысл добавить две временные области, но не имеет смысла добавлять две даты , если у вас нет произвольной контрольной даты . Не допуская добавления дат, вы абстрагируете эту произвольную ссылочную дату. Я не знаю, какая дата '0' в .Net, и мне никогда не нужно было знать. Разве это не хорошо?

Добавление двух дат почти всегда является ошибкой (серьезно, попробуйте подумать, где это имеет смысл вне нумерологии). Вводя временные рамки (создавая Affine Space ), вы устраняете целый класс ошибок.

4 голосов
/ 19 сентября 2009

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

Кроме того, IntelliSense (и обнаружение для новичков) работает лучше, когда число членов меньше - разделение методов между двумя типами упрощает работу с каждым из них.

2 голосов
/ 20 сентября 2009

Думайте об этом концептуально. Если я скажу вам, что у меня вечеринка через 7 дней, это «7 дней» в этом предложении дата. Могу ли я просто сказать, что моя вечеринка на 7 дней? Конечно нет, потому что 7 дней не дата. Одна из ключевых идей объектно-ориентированного программирования - представлять такие понятия в системе как типы. Это правда, что мы могли бы представить все как целое число (и на самом деле, многие люди имеют и делают), но в объектно-ориентированном программировании мы имеем представление о типах элементов, их поведении и свойствах, и в этом смысле это делает смысл иметь объект, который выражает это.

2 голосов
/ 19 сентября 2009

Спросили наоборот: какая польза от ослабления системы типов в этом отношении?

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

И наоборот, стоит иметь DateTime: zilch.

Теперь рассмотрите возможность сброса DateTime. Что бы мы получили?

Чтобы прямо ответить на ваш вопрос: «не является ли TimeSpan избыточным?» Абсолютно нет, это уменьшает количество ошибок. Это определенно для меня.

0 голосов
/ 15 июля 2011

В датах много сложностей, например:

  • високосные годы
  • високосных секунд
  • переход на 1582 год по григорианскому календарю
  • тот факт, что нет такой вещи, как 0 лет
  • Различия в продолжительности месяцев

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

0 голосов
/ 19 сентября 2009

Я думаю, вы могли бы сделать противоположный аргумент, что DateTime является избыточным, и у нас должно быть только TimeSpan:)

Серьезно, все даты на самом деле просто промежутки времени. Все они относительно некоторой отправной точки. Технически, в христианском календаре нет «нулевого года» (поскольку у нас не может быть «нулевого года нашего господина»), но если мы назначим 12:00 утра. 1 января 0001 г. до н. Э. как «нулевая точка», то каждая дата, которая следует после (или до), может рассматриваться как относительная к этой дате. Итак, 12:00 утра 19 сентября 2009 года срок службы составит 734033 дня.

Итак, математически , DateTime и TimeSpan являются избыточными. Но когда мы пишем код, мы пытаемся общаться гораздо больше, чем просто абстрактные математические конструкции. Любой данный экземпляр DateTime может фактически быть промежутком времени относительно некоторой произвольной нулевой точки, но для большинства людей, читающих ваш код, это подразумевает определенную точку в календаре. Точно так же, TimeSpan подразумевает разрыв между двумя точками в календаре.

В этом случае Microsoft решила быть ясной, а не скупой. Не могу сказать, что не согласен с решением.

0 голосов
/ 19 сентября 2009

его сахар не более или менее ....

...