Является ли TimeSpan ненужным?
РЕДАКТИРОВАТЬ 2009-Nov-04
Итак, прошло немного времени с тех пор, как я впервые опубликовал этот вопрос. Мне кажется, что многие из первых респондентов не смогли по-настоящему понять то, что я говорил - общим ответом было несколько вариантов "То, что вы говорите, не имеет никакого смысла"- и поэтому я сделал несколько удобных диаграммы, чтобы действительно проиллюстрировать мою точку зрения.
Когда мы говорим о числах, мы, как правило, имеем в виду те моменты, которые учащиеся начальной школы изучают как "Числовая линия":
Теперь, когда мы изучаем арифметику, наши умы учатся выполнять очень интересную трансформацию этой концепции. Оценивая выражение 1 + 0.5
Например, если бы мы просто применили наше "мышление числовой линии", нам бы потребовалось как-то разобраться в этом:
Трудно действительно это проиллюстрировать, потому что об этом сложно подумать: "добавить" два пункта. Именно здесь многие респонденты боролись с идеей добавления дат (или просто отклонили это как абсурдное), потому что они думали о датах как о точках.
Тем не менее, выражение 1 + 0.5
имеет смысл для нас, потому что, когда мы думаем об этом, мы действительно воображаем это:
То есть число (или точка) 1 плюс вектор 0,5, в результате чего получается точка 1,5.
С другой стороны, мы можем представить себе это:
То есть вектор 1 плюс вектор 0,5, в результате чего получается вектор 1,5.
Другими словами, когда мы имеем дело с числами, мы рассматриваем точки и векторы взаимозаменяемо. Но как насчет дат? Даты, в конце концов, в основном числа. Если вы мне не верите, сравните эту строку с числовой строкой выше:
Заметили соответствие между временной шкалой и числовой линией? Это была моя точка зрения: если мы выполним преобразование выше с числами, мы должны быть в состоянии сделать это и с датами. Итак, применяя "временную шкалу мышления", выражение 0001-Jan-02 00:00:00 + 0001-Jan-01 12:00:00
не имеет большого смысла, так как многие респонденты указали:
Но, если мы делаем то же самое концептуальное преобразование в нашей голове, которое мы выполняем каждый раз, когда добавляем или вычитаем числа, мы можем легко "переосмыслить" вышеприведенное:
Так ясно, разница между DateTime
и TimeSpan
та же разница, что существует между точкой и вектором. Я думаю, что многие люди негативно отреагировали на мое предположение о том, что так неестественно воспринимать даты как величины таким образом. Но я не согласен с аргументом о том, что нет очевидного ориентира для использования в качестве нуля. Существует очевидный ориентир, и я дам вам подсказку, где он находится: около 2010 года назад.
Не поймите меня неправильно: я не подвергаю сомнению полезность проведения концептуального разрыва между понятием DateTime
и TimeSpan
, Действительно, мой вопрос должен был быть (как косвенно предложил ChrisW), почему мы рассматриваем числа и векторы взаимозаменяемо при работе с обычными числовыми типами? (Или: почему у нас только один int
тип, а не int
а также intspan
?) Есть большая разница, и все же мы никогда не думаем об этом до тех пор, пока не начнем в средней школе или средней школе, когда мы начнем геометрию. И затем это воспринимается как новая математическая концепция, когда в действительности это то, что мы используем с тех пор, как научились складывать числа, считая их пальцами.
В конце концов, лучший ответ пришел от Strilanc, который указал, что использование DateTime
а также TimeSpan
на самом деле является реализацией аффинного пространства, которое имеет удобное свойство: ему не нужна точка отсчета, которая рассматривается как источник. Так что спасибо, Стриланк. Тем не менее, я даю признанный ответ ChrisW за то, что был первым, кто поднял концепцию векторов и точек, которая действительно дошла до сути вопроса.
ОРИГИНАЛЬНЫЙ ВОПРОС (для потомков)
Я, конечно, не программистский мастер на все руки, но я знаю, что и PHP, и.NET имеют TimeSpan
класс в дополнение к DateTime
класс (или структура в.NET), и я предполагаю, что это имеет место и во множестве других языков и сред (хотя я пишу это прежде всего со ссылкой на.NET структуры). Это может показаться странным вопросом, но это не так TimeSpan
лишний?
Если вы думаете, что ответ очевиден ("А DateTime
является абсолютным моментом времени, а TimeSpan
это интервал времени - просто так!"), подумайте вот что: целое число может быть концептуализировано как абсолютное значение (точка на числовой линии) или расстояние между значениями - и нам не нужны два отдельных типы данных для этих различных концептуализаций. Я все еще могу написать 5 + 6 без какой-либо двусмысленности относительно того, что я имею в виду.
Пока существует постоянная ссылка на нулевую точку, мне кажется, что не должно быть никаких причин, по которым TimeSpan
объект для выполнения арифметических операций над DateTime
объекты, или чтобы получить расстояние между ними.
Что мне не хватает? Почему не могут уникальные методы и свойства TimeSpan
структура просто складывается в DateTime
?
(Отказ от ответственности: это не так, как я увлечен этим или что-то; я в порядке, используя DateTime
а также TimeSpan
объекты, как они предназначены все время. Я просто задаю вопрос.)
РЕДАКТИРОВАТЬ: Хорошо, слишком упрощенный пример, чтобы проиллюстрировать мою точку зрения:
Рассмотрим уравнение 10 - 5 = 5. Можно было бы прочитать это как "Начните с 10 (значение), переместитесь на 5 влево (диапазон), и вы в конечном итоге на 5 (значение)".
Предположим, чтобы упростить задачу, мы позволим 1 января 1900 года быть нулевой точкой и определим TimeSpan
объекты только по дням.
Тогда 10 - 5 = 5 можно понять, в DateTime
термины, как 1 1 января 1900 г. - 6 января 1900 г. = 6 января 1900 г. Это хорошо, потому что 1 1 января - это просто "10" по нашему определению, а 6 января - "5". Тот факт, что мы рассматриваем 10 как значение, первые 5 как промежуток, а последние 5 снова как значение, это просто для нашей собственной концептуальной выгоды. Суть в том, что единственное различие заключается в том, как вы думаете о числе, а не в том, как оно есть на самом деле. Вот почему у нас нет отдельных структур, скажем, для целочисленных значений и целых интервалов - простое старое целое число охватывает все наши базы.
Имею ли я какой-то смысл?
10 ответов
Учтите это: целое число может быть понято как абсолютное значение (точка на числовой линии) или расстояние между значениями.
По вашей логике, это не TimeSpan, что не нужно: скорее это DateTime, который не нужен, и может быть заменен на TimeSpan (продолжительность с нуля).
Плюс есть тот факт, что целые числа имеют очевидный ноль, в то время как Даты, однако, не имеют явного нуля; но наличие очевидного нуля необходимо, если вы хотите заменить "место на числовой линии" на "расстояние / расстояние от нуля / начало координат".
Редактировать:
Точка (местоположение на плоскости) отличается от вектора.
Они кажутся похожими...
- Вектор (расстояние от начала координат) может представлять точку
- Точка (относительно начала координат) может представлять вектор
... однако значение вектора, которое требуется для представления данной точки, изменится, если начальная точка изменится.
Всегда имеет смысл добавлять два (относительных) вектора; но нет смысла добавлять две точки, кроме как путем преобразования этих точек в векторы, а затем добавления векторов.
Изменение двух векторов не влияет на сумму двух векторов, но изменение источника может повлиять на сумму двух точек, если их суммировать, преобразовав их в векторы и добавив векторы (поскольку изменение источника повлияет на значения этих векторов).
[Замените 'point' на DateTime, а 'vector' на TimeSpan в приведенном выше аргументе.]
Я думаю, что есть абсолютная разница между абсолютными и относительными значениями. Я не знаю, почему это различие не является более очевидным в арифметике, то есть почему "числа" используются, по-видимому, взаимозаменяемо для представления как абсолютных, так и относительных значений.
Дата не ведет себя как целое число, я не могу вспомнить классификацию алгебры, но учту это:
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 = ???
Это последнее вычисление может быть интерпретировано как значимое, когда мы рассматриваем Date как Days-since-StartDate. Но значение будет таким же произвольным, как и значение StartDate.
(Говоря как математик) Это потому, что арифметические операции с "датой" не являются закрытыми или четко определены, что требует необходимости в дополнительной структуре.
Например, 1 января 2000 г. - 1 декабря 1999 г. = ...? Мы знаем, что между ними 31 день, но если это было истолковано как дата, то ответ - Эпоха (т. Е. Ноль) + 31 день. Это больше не является действительной "датой".
Точно так же все арифметические операции над целыми числами не определены должным образом (1 / 2 не имеет ответа в целых числах. Здесь целочисленная математика возвращает ноль, но 0 * 2 = 0, а не 1, как вы ожидаете). Это вызывает необходимость в дополнительной структуре, которую мы называем дробями.
То, что вы можете определить операцию, не означает, что вы должны это делать. Например, одна из причин, по которой деление на ноль не определено, заключается в том, что для его определения потребуется пожертвовать некоторыми очень полезными свойствами арифметики (например, ассоциативность и т. Д.).
Различие между временем и датой сводится к сложению. Имеет смысл добавить два интервала времени, но нет смысла добавлять две даты, если у вас нет произвольной контрольной даты. Не допуская добавления дат, вы абстрагируете эту произвольную ссылочную дату. Я не знаю, какая дата '0' в.Net, и мне никогда не нужно было знать. Разве это не мило?
Добавление двух дат почти всегда является ошибкой (серьезно, попробуйте подумать, где это имеет смысл вне нумерологии). Вводя временные рамки (создавая Affine Space), вы устраняете целый класс ошибок.
Одна из причин заключается в том, что разделение типов предотвращает класс ошибок, когда вы думаете, что у вас есть относительное время, но действительно есть абсолютное время, и наоборот. Например, сложение двух абсолютных времен может быть помечено как ошибка компилятора, если эти два типа разделены.
Кроме того, IntelliSense (и обнаружение для новичков) работает лучше, когда число членов меньше - разделение методов между двумя типами упрощает работу с каждым из них.
На вопрос об обратном: какая польза от ослабления системы типов в этом отношении?
Это все вопрос стоимости против выгоды и DateTime
имеет большое преимущество уменьшения ошибок из-за нелогичных вычислений даты / времени, запрещая такие действия. DateTime
существует по тем же причинам, по которым в первую очередь существует строгая система проверки типов: чтобы семантические ошибки в коде создавали сообщения во время компиляции. которые уведомляют программистов об ошибках в их коде.
И наоборот, есть цена DateTime
: zilch.
Теперь рассмотрим падение DateTime
, Что бы мы получили?
Чтобы ответить на ваш вопрос напрямую: "не TimeSpan
избыточно? "Абсолютно нет, это уменьшает количество ошибок. Это определенно для меня.
Думайте об этом концептуально. Если я скажу вам, что у меня вечеринка через 7 дней, это "7 дней" в этом предложении дата. Могу ли я просто сказать, что моя вечеринка на 7 дней? Конечно нет, потому что 7 дней не дата. Одна из ключевых идей объектно-ориентированного программирования - представлять такие понятия в системе как типы. Это правда, что мы могли бы представить все как целое число (и на самом деле, многие люди имеют и делают), но в объектно-ориентированном программировании у нас есть понятие типов элементов, а также их поведение и свойства, и в этом смысле это делает смысл иметь объект, который выражает это.
Я думаю, что вы могли бы сделать противоположный аргумент DateTime
избыточно, и мы должны иметь только TimeSpan
:)
Серьезно, все даты действительно просто промежутки времени. Все они относительно какой-то отправной точки. Технически, в христианском календаре нет "нулевого года" (поскольку вы не можете иметь "нулевой год нашего господина"), но если мы назначим 12:00 утра 1 января 0001 г. до н.э. в качестве "нулевой точки" тогда каждая дата, которая наступает после (или до), может рассматриваться как относительная к этой дате. Таким образом, в 12:00 19 сентября 2009 года интервал времени составит 734033 дня.
МатематическиDateTime
а также TimeSpan
избыточны. Но когда мы пишем код, мы пытаемся общаться гораздо больше, чем просто абстрактные математические конструкции. Любой данный DateTime
Фактически, экземпляр может быть просто промежутком времени относительно некоторой произвольной нулевой точки, но для большинства людей, читающих ваш код, это будет означать определенную точку в календаре. Точно так же, TimeSpan
подразумевает разрыв между двумя точками в календаре.
В этом случае Microsoft решила быть ясной, а не экономной. Не могу сказать, что не согласен с решением.
В датах много сложностей, например:
- високосные годы
- високосные секунды
- 1582 переход на григорианский календарь
- тот факт, что нет такой вещи, как 0 лет
- различия в продолжительности месяцев
Отношение к датам и временным интервалам, как к разным вещам, означает, что такого рода проблемы гораздо реже смущают вас на практике.