TimeSpan不必要吗?

Dan*_*Tao 17 language-agnostic datetime timespan

编辑2009年11月4日

好的,自从我第一次发布这个问题以来已经有一段时间了.在我看来,许多最初的响应者都没能真正得到我所说的 - 一个共同的反应是"你所说的没有任何意义"的一些变化 - 所以我做了一些方便图表真的说明了我的观点.

当我们谈到数字时,我们通常指的是学校儿童学习的等级被称为数字线:

数字线

现在,当我们学习算术时,我们的思想学会对这个概念进行非常有趣的转换.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并没有多大意义,因为很多响应者指出:

在时间轴上添加两个点

但是,如果我们在每次添加或减去数字时执行相同的概念转换,我们可以轻松地"重新考虑"上述内容:

添加时间点和时间向量

很明显,a DateTime和a 之间的TimeSpan差异与点和矢量之间存在的差异相同.我认为让很多人对我的建议做出负面反应的是,以这种方式将日期视为大小只是感觉如此不自然.但我不认为没有明显的参考点可以用作零.有一个明显的参考点,我会给你一个暗示:大约在2010年前.

不要误解我的意思:我不是在质疑a 和a 的概念之间划分概念的有用性.说真的,我的问题一直以来应该是(为ChrisW间接暗示),为什么我们对待数字和载体互换与普通数字类型打交道?(或者:为什么我们只有一种类型,而不是和?)有一个很大的区别,但是在初中或高中,当我们开始几何时,我们从来没有真正考虑过它.然后它被视为这个新的数学概念,而实际上它是我们一直在利用的东西,因为我们通过用手指计数来学习添加数字.DateTimeTimeSpanintintintspan

最后,最好的答案来自Strilanc,他指出使用DateTimeTimeSpan实际上是仿射空间的实现,它具有不需要参考点作为原点的方便性.谢谢,Strilanc.然而,我给出了ChrisW的接受答案,因为他是第一个提出矢量和点的概念的人,这真正解决了问题的关键.


原始问题(后代)

我当然不是所有行业的编程插孔,但我知道PHP和.NET TimeSpan除了DateTime类(或.NET中的结构)之外还有一个类,我猜这是各种其他语言和框架的情况.同样(虽然我主要是参考.NET结构编写的).这似乎是一个奇怪的问题,但不是TimeSpan多余的?

如果您认为答案是显而易见的("A DateTime是一个绝对时间点,而a TimeSpan是一个时间范围 - 就像那样简单!"),请考虑这一点:整数可以概念化为绝对值(点在数字线上)或值之间的距离- 我们不需要两个单独的数据类型用于这些不同的概念.关于我的意思,我仍然可以写出5 + 6而没有任何含糊之处.

只要存在一致的零点引用,在我看来应该没有理由为什么需要一个TimeSpan对象来对DateTime对象执行算术运算,或者为了获得它们之间的距离.

我错过了什么?为什么TimeSpan结构的独特方法和属性不能简单地折叠成DateTime

(免责声明:这并不像我对这个或任何事情充满热情;我很好地使用DateTimeTimeSpan对象,因为他们一直都在想.我只是问一个问题.)

编辑:好的,过于简化的例子来说明我的观点:

考虑等式10 - 5 = 5.可以将其读作"从10开始(值),向左移动5(跨度),最后到5(值)."

假设,为了简单起见,我们让1900年1月1日为零点,我们TimeSpan只用天来定义对象.

然后10 - 5 = 5可以理解DateTime为1900年1月11日 - 1900年1月6日= 1900年1月6日.这很好,因为根据我们的定义,1月11日只是"10",1月6日是"5".事实上,我们将10视为一个,前5个视为一个范围,而后五个再视为一个,这仅仅是为了我们自己的概念上的好处.我的观点是这样的:唯一的区别在于你如何看待这个数字,而不是它实际上是什么.这就是为什么我们没有单独的结构,比如整数值和整数跨度 - 一个普通的旧整数覆盖了我们所有的基础.

我有意义吗?

Hen*_*man 18

Date不像整数,我不记得代数的分类,但考虑到这一点:

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

Span + Span = Span
Span - Span = Span
Run Code Online (Sandbox Code Playgroud)

对于任何一年,

10 feb + 10 days = 20 feb
20 feb - 20 jan  = 31 days
20 jan + 20 feb  = ???
Run Code Online (Sandbox Code Playgroud)

当我们将Date视为Days-since-StartDate时,最后一次计算可能会被解释为有意义.但是这个值和StartDate的选择一样随意.

  • 啊,我发现了我在维基百科上谈论的内容.点/向量和日期/时间跨度各自形成一个仿射空间(http://en.wikipedia.org/wiki/Affine_space). (4认同)
  • 仅仅因为你*可以*定义一个操作并不意味着你*应该*.通过不允许日期添加,我们可以抽象出任意的"日期零".作为奖励,它还消除了一系列错误,当您想要添加时间跨度时添加日期.我在几何库中使用相同的技术(无法添加点,但差异给出了矢量)的原因相同:添加两个点几乎可以保证是一个错误. (3认同)

Set*_*eth 12

(作为数学家说)这是因为"日期"上的算术运算没有封闭或定义明确,因此需要额外的结构.

例如,2000年1月1日 - 1999年12月1日= ......?我们知道他们之间有31天,但如果这被解释为日期,那么答案是大纪元(即零)+ 31天.这不再是有效的"日期".

类似地,对整数的所有算术运算都没有很好地定义(1/2在整数中没有答案.整数数学在这里返回零,但是0*2 = 0,而不是你想象的1).这需要一个我们称之为分数的附加结构.

  • 出于各种原因,我最喜欢的是在1528年左右引入格里高利历之前,"日"的长度与现在不同.因此,如果你有一个知道这些事情的DateTime实现,(Date1 - Date2)+ Date2!= Date1.(.NET实现非常好,但我不知道它是否会为你提供日历). (2认同)

Chr*_*isW 12

考虑到这一点:整数可以概念化为绝对值(数字线上的点)或值之间的距离

按照你的逻辑,TimeSpan不是必要的:而不是DateTime,这是不必要的,可以被TimeSpan取代(从零开始的持续时间).

另外,整数有一个明显的零,而日期则没有明显的零; 但如果要将"数字线上的位置"替换为"距零/原点的距离/跨度",则必须具有明显的零.


编辑:

点(平面上的位置)与矢量不同.

它们看似相似......

  • 矢量(距离原点的距离)可以表示一个点
  • 点(相对于原点)可以表示矢量

...但是,如果原点发生变化,表示给定点所需的矢量值将发生变化.

添加两个(相对)向量总是有意义的; 但是,添加两个点是没有意义的,除了将这些点转换为矢量然后添加矢量.

两个向量的总和不受原点变化的影响,但是如果通过将它们转换为向量并添加向量来对它们进行求和,则两个点的总和将受到原点变化的影响(因为更改原点会影响原点)这些载体的值).

[在上面的参数中用TimeSpan替换'point'和'vector'与'vector'.]

我认为绝对值和相对值之间存在真正的差异.我不知道为什么这种差异在算术中并不明显,即为什么"数字"似乎可以互换地用来表示绝对值和相对值.

  • @Joren如果你能找到另一个整数new_zero,使得new_zero*x = new_zero,对于所有整数x都为真,那么你可以说零是相对的. (2认同)

Cra*_*ney 5

仅仅因为你可以定义一个操作并不意味着你应该.例如,除以零的原因之一是未定义的,因为定义它将需要牺牲一些非常有用的算术属性(例如,关联性等).

时间跨度和日期之间的区别归结为添加.添加两个timepans是有意义的,但除非你有一个任意的参考日期,否则添加两个日期是没有意义的.通过不允许添加日期,您抽象出任意参考日期.我不知道.Net中的'0'是什么日期,我从来不需要知道.不是很好吗?

添加两个日期几乎总是一个错误(严重的是,试着想一想除数字命理之外哪些是有意义的).通过引入时间跨度(创建仿射空间),您可以消除一整类错误.