我想将时间存储在数据库表中,但只需要存储小时和分钟。我知道我可以只使用DATETIME并忽略日期的其他组成部分,但是在不存储超出我实际需要的更多信息的情况下,最好的方法是什么?
我想将时间存储在数据库表中,但只需要存储小时和分钟。我知道我可以只使用DATETIME并忽略日期的其他组成部分,但是在不存储超出我实际需要的更多信息的情况下,最好的方法是什么?
Answers:
您可以将其存储为午夜后分钟数的整数:
例如。
0 = 00:00
60 = 01:00
252 = 04:12
但是,您需要编写一些代码来重新构造时间,但这并不容易。
DATETIME开始DATETIME结束
我恳求您使用两个DATETIME值代替,它们标记为event_start和event_end之类的东西。
时间是一项复杂的业务
现在,世界上大多数国家正确或错误地采用了基于牙科的度量系统。总体而言,这是件好事,因为至少我们都可以同意,ag是毫升,是立方厘米。至少大约是这样。公制存在许多缺陷,但至少在国际上一直存在缺陷。
随着时间的流逝,我们有了;每秒1000毫秒,每秒60秒到一分钟,每小时60分钟到一小时,每天半天12个小时,每月大约30天,具体时间取决于所讨论的月份和年份,每个国家/地区与其他国家/地区的时间会有所不同,每个国家/地区的时间格式都有所不同。
有很多东西需要消化,但是对于一个如此复杂的场景来说,有一个简单的解决方案是不可能的。
可以切掉一些角落,但是有些地方最好不要
尽管此处的最高答案表明您可能在午夜之后存储了整整几分钟的时间似乎是完全合理的,但我已经学会了避免这样做。
实现两个DATETIME值的原因是为了提高准确性,分辨率和反馈。
当设计产生不良结果时,这些都非常方便。
我存储的数据是否超出要求?
最初看起来好像要存储比我需要的更多的信息,但是有充分的理由接受这一打击。
从长远来看,存储这些额外的信息几乎总会节省我的时间和精力,因为我不可避免地发现,当有人被告知某件事花了多长时间时,他们还会想知道事件的发生时间和地点。
这是一个巨大的星球
过去,我一直犯有无视我的星球之外还有其他国家的罪行。当时这似乎是个好主意,但这总是会导致问题,头痛和浪费时间。始终考虑所有时区。
C#
DateTime很好地呈现为C#中的字符串。ToString(string Format)方法紧凑且易于阅读。
例如
new TimeSpan(EventStart.Ticks - EventEnd.Ticks).ToString("h'h 'm'm 's's'")
SQL服务器
同样,如果您要读取的数据库与应用程序界面是分开的,则dateTimes可以一目了然地读取,并且对它们执行计算非常简单。
例如
SELECT DATEDIFF(MINUTE, event_start, event_end)
ISO8601日期标准
如果使用SQLite,则没有此功能,因此应使用“文本”字段并将其以ISO8601格式存储,例如。
“ 2013-01-27T12:30:00 + 0000”
笔记:
使用24小时制*
ISO8601的时间偏移量(或+0000)部分直接映射到GPS坐标的经度值(不考虑夏令时或全国范围)。
例如
TimeOffset=(±Longitude.24)/360
...其中±是指东西方向。
因此,值得考虑是否值得将经度,纬度和高度与数据一起存储。这将因应用而异。
ISO8601是国际格式。
对于http://en.wikipedia.org/wiki/ISO_8601上的更多详细信息,Wiki非常有用。
日期和时间以国际时间存储,而偏移量则根据存储时间在世界的哪个地方记录。
根据我的经验,始终需要存储完整的日期和时间,而不管我是否认为开始该项目的时间。ISO8601是一种很好的,面向未来的方法。
免费提供其他建议
同样值得将事件像链子一样组合在一起。例如,如果记录比赛,则整个事件可以按racer,race_circuit,circuit_checkpoints和circuit_laps分组。
以我的经验,确定谁存储记录也是明智的。可以是通过触发器填充的单独表,也可以是原始表中的其他列。
投入越多,得到的越多
我完全理解在空间上尽可能节约的愿望,但是我很少这样做,而以丢失信息为代价。
如标题所述,数据库的经验法则是,数据库只能告诉您所拥有的数据,而回溯历史数据并填补空白可能非常昂贵。
解决的办法是第一次使其正确。这当然说起来容易做起来难,但是现在您应该对有效的数据库设计有更深刻的了解,并且随后有很大的机会将它第一次正确设置。
您的初始设计越好,以后的维修费用就越少。
我只说所有这一切,因为如果我能时光倒流的话,那就是我到那里时会告诉自己的东西。
只需存储一个常规日期时间,然后忽略其他所有内容即可。当您可以只加载日期时间时,为什么还要花额外的时间编写代码来加载一个int,对其进行处理并将其转换为datetime呢?
DATETIME
数据类型需要占用4个字节来存储,而SMALLINT
例如,一个数据类型只需要占用其中的四分之一。如果只有几千行,没什么大不了,但是,如果像许多公司一样拥有数百万行,那么您节省的空间将是可观的。
SQL Server实际上将时间存储为一天的一部分。例如,一整天=值1。12小时是0.5的值。
如果要在不使用DATETIME类型的情况下存储时间值,则以十进制形式存储时间将适合这种需要,同时还可以使转换为DATETIME变得简单。
例如:
SELECT CAST(0.5 AS DATETIME)
--1900-01-01 12:00:00.000
将值存储为DECIMAL(9,9)将占用5个字节。但是,如果精度不是最重要的,那么REAL将仅消耗4个字节。无论哪种情况,都可以很容易地根据数字值而不是数据/时间类型来计算汇总计算(即平均时间)。
我们将其存储为24小时制,而不是分钟过去的午夜,而是存储为SMALLINT。
09:12 = 912 14:15 = 1415
当转换回“可读格式”时,我们只需在右边插入两个冒号“:”。如果需要,请用零填充左键盘。每种方式保存数学,并使用更少的字节(与varchar相比),并强制将值设为数字(而不是字母数字)
虽然非常愚蠢...但应该已经在MS SQL中存在TIME数据类型很多年了...恕我直言...
我想您需要的是一个变量,它将分钟数存储为数字。这可以通过不同类型的整数变量来完成:
SELECT 9823754987598 AS MinutesInput
然后,在您的程序中,您可以通过以下方式简单地以所需的形式查看此内容:
long MinutesInAnHour = 60;
long MinutesInADay = MinutesInAnHour * 24;
long MinutesInAWeek = MinutesInADay * 7;
long MinutesCalc = long.Parse(rdr["MinutesInput"].toString()); //BigInt converts to long. rdr is an SqlDataReader.
long Weeks = MinutesCalc / MinutesInAWeek;
MinutesCalc -= Weeks * MinutesInAWeek;
long Days = MinutesCalc / MinutesInADay;
MinutesCalc -= Days * MinutesInADay;
long Hours = MinutesCalc / MinutesInAnHour;
MinutesCalc -= Hours * MinutesInAnHour;
long Minutes = MinutesCalc;
您要求使用效率时会出现问题。但是,如果您时间紧缺,则只需使用可为空的BigInt来存储您的分钟数。
值为null表示尚未记录时间。
现在,我将以往返于外层空间的形式进行解释。
不幸的是,一个表列将只存储一个类型。因此,您将需要根据需要为每种类型创建一个新表。
例如:
如果MinutesInput = 0 .. 255,则使用TinyInt(如上所述进行转换)。
如果MinutesInput = 256 .. 131071,则使用SmallInt(注意:SmallInt的最小值为-32,768。因此,在存储和检索值时取反并加32768,以在如上所述进行转换之前利用整个范围)。
如果MinutesInput = 131072 .. 8589934591,则使用Int(注意:取反并根据需要添加2147483648)。
如果MinutesInput = 8589934592 .. 36893488147419103231,则使用BigInt (注意:根据需要添加和否定9223372036854775808)。
如果MinutesInput> 36893488147419103231,则我个人将使用VARCHAR(X)根据需要增加X,因为char是一个字节。我将不得不在稍后的日期重新讨论该答案以完整描述它(或者也许有一个stackoverflowee可以完成这个答案)。
因为每个值无疑都需要唯一的键,所以只有在存储的值的范围在很小(接近0分钟)和很大(大于8589934591)之间很好地混合时,数据库的效率才会显现出来。
在存储的值实际达到大于36893488147419103231的数值之前,您还可能只有一个BigInt列来表示分钟,因为您无需将Int浪费在唯一的标识符上,而将另一个Int浪费在存储分钟值上。
ticks
将long
/ 存储为/ bigint
,当前以毫秒为单位。可以通过查看更新的值来找到TimeSpan.TicksPerSecond
值。
大多数数据库都具有DateTime类型,该类型可以自动将时间存储为幕后的滴答声,但是在某些数据库(例如SqlLite)的情况下,存储滴答声可以作为存储日期的一种方式。
大多数语言允许从简单的转换Ticks
→交通TimeSpan
→交通Ticks
。
例
在C#中,代码为:
long TimeAsTicks = TimeAsTimeSpan.Ticks;
TimeAsTimeSpan = TimeSpan.FromTicks(TimeAsTicks);
但是请注意,因为在SqlLite的情况下,它仅提供少量的不同类型,它们分别是:INT
,REAL
并且VARCHAR
必须将刻度的数目存储为字符串或两个INT
单元格的组合。这是因为an INT
是32位带符号数字,而BIGINT
64位带符号数字。
注意
但是,我个人的喜好是将日期和时间存储为ISO8601
字符串。