我已阅读其他一些有关此问题的帖子。大多数答案建议将日期/时间数据转换为特定格式(UTC)并将其存储在字符串dataType中。
以整数格式存储它们是否“合适”,每个数据(年,月,日,小时,分钟)存储1列?或者这是不可接受的?因为这会比较当前日期/时间更容易。我打算做的是行的数据是否超过当前日期。
Java代码:
compareTo
答案 0 :(得分:5)
使用:
YYYY-MM-DDTHH:MM:SS.S…Z
2016-09-17T18:28:27Z
Answer by GVillani82是正确的,应该被接受。唯一的问题是引用错误地声明的SQLite文档:
TEXT as ISO8601字符串(" YYYY-MM-DD HH:MM:SS.SSS")
该陈述中有两点错误:中间的SPACE和小数的三位数。
中间T
严格来说,中间有空格的格式不符合ISO 8601。 ISO 8601标准中间需要T
而不是SPACE。引用总结ISO 8601标准的the Wikipedia page:
...连接一个完整的日期表达式,字母T作为分隔符,以及一个有效的时间表达式。例如," 2007-04-05T14:30"。
只有在数据的发件人和收件人的特殊安排下,T
才可以替换为SPACE。
进一步令人困惑的是,中间中的SPACE格式符合SQL标准的日期时间格式定义。 SQL规范早于ISO 8601.ISO 8601正在迅速成为首选格式,因为它继续在全球范围内被商业世界以及现代计算机协议采用。
ISO 8601标准允许以秒为单位的小数位数的任意位数。引用的文件意味着需要三个数字,但实际上允许任何数字包括零(根本没有数字,整数秒)。
三位数代表milliseconds,六位是microseconds,九位是nanoseconds。这些都是主流面向商业的应用程序中常用的。任何更精细的分数只能在科学/工程类型的应用程序中看到。
java.time类使用nanosecond分辨率,而旧的日期时间Java类仅限于毫秒。
这两个问题不仅仅是学术问题,而是提出了实际问题。
在Java环境中,我们可能会从SQLite中提取此字符串,然后将其作为java.time对象进行削减。 java.time类是处理日期时间编程的现代方法。这个框架的灵感来自Joda-Time(同一个人领导的努力,Stephen Colbourne),由JSR 310定义,内置于Java 8及更高版本,正式取代了麻烦的旧日期时间类,后端移植到Java 6& ThreeTen-Backport项目中的7,并进一步适应Android项目中的ThreeTenABP。
在解析/生成表示日期时间值的字符串时,java.time类默认使用标准ISO 8601格式。但是java.time只使用严格的定义。这意味着在日期时间中间T
。
Instant instant = Instant.parse( "2016-09-17T18:28:27Z" );
问题是,解析由SQLite doc错误标记为ISO 8601的格式,中间是SPACE将无法通过java.time解析。另一方面,默认情况下java.time生成的字符串中间会有T
而不是空格。
解决方案很简单:只需使用严格的ISO 8601定义,中间有T
。
如果您在SQLite documentation page on date-time functions内阅读得足够深,则会看到它提到:
..." T"是按照ISO-8601
的要求分隔日期和时间的文字字符
SQLite及其日期时间函数支持T
格式。此外,该文件还指出,Z
UTC Zulu
的时区指标也受支持。
...可以选择性地跟随形式的时区指示符" [+ - ] HH:MM"或只是" Z"。日期和时间功能使用UTC或" zulu"内部时间,所以" Z"后缀是无操作。
所以我建议在SQLite中存储片刻的最明智的方法是调整为UTC并使用严格的ISO 8601格式,包括最后的Z
:2016-09-17T18:28:27Z
对于小数秒,SQLite文档说虽然只有前三个小数位数对其SQLite函数有意义,但实际上可以存储任意数量的数字。因此,java.time中允许的纳秒数的最大9位数显然可以成功存储,但不正好比较:2016-09-17T18:28:27.123456789Z
如果此比较精度是您的应用程序的问题,您可以使用可处理纳秒的java.time类在应用程序的Java端进行比较工作,或者您可以考虑将日期时间值截断为毫秒解析度。 java.time类提供了一种方便的截断方法。
选项怎么样?
Floating point technology用于实数,例如float
/ Float
& Java中的double
/ Double
,故意以准确性换取执行速度。这意味着无关数字通常出现在分数的右侧。虽然这在某些科学/工程/游戏领域是可以容忍的,但在金钱问题和日期时间值的某些用途方面是不可接受的。所以,在我看来,这不是一个好主意。
来自epoch的计数,例如自UTC 1970年以来的秒数,这不是一个好主意。虽然java.time类在封面下使用这种方法来实际跟踪时间,但我们有这些封面是有原因的。这样的整数对于人类读者没有意义,没有日期时间值可以辨别,因此可能无法检测到错误。数据类型本身是模糊的,因为我们必须猜测一些计算机系统使用整秒作为计数的预期粒度,其他计算机系统使用毫秒或微秒或纳秒或其他粒度。至于时代,这也是模棱两可的,因为在各种计算系统中至少使用了couple dozen epoch points。
请注意,SQLite从未打算成为一个严肃的重型数据库。因此,SQLite中的lite
。 inventor has explained他希望SQLite成为编写纯文本文件的升级替代方案。他从不打算让SQLite成为更严肃的数据库的竞争者。
因此,如果您遇到SQLite限制的痛点,您的需求可能超出了SQLite的设计参数。如果您需要更严肃的数据库,请使用更严肃的数据库。
在Android环境中,我首先考虑的是H2 Database Engine。这种纯Java,开源,免费的数据库产品正在积极开发并越来越受欢迎。参见:
答案 1 :(得分:4)
根据Sqlite documentation (section 2.2),您应该通过以下方式之一存储日期:
比较问题可以使用strftime函数来解决,该函数允许您主持其存储类型(TEXT,REAL或INTEGER)的日期。
让我们说你想要获得数据库中所有具有日期Jenuary的行。你可以这样做:
SELECT * FROM table
WHERE strftime('%m', your_date_column) == '01'
或许你想要时间09:40获取所有行:
SELECT * FROM table
WHERE strftime('%H:%M', your_date_column) == '09:40'
或者:
SELECT * FROM table
WHERE strftime('%s', your_date_column) < strftime('%s','now')
将返回当前日期(现在)之前的日期的所有行。
摘要:函数strftime
抽象出数据库存储模式,因此它实际上并未满足您使用的模式。