SQLite中两个日期之间的差异


110

如何获得SQLite中两个日期之间的天数差异?我已经尝试过这样的事情:

SELECT Date('now') - DateCreated FROM Payment

每次返回0。

Answers:


123
 SELECT julianday('now') - julianday(DateCreated) FROM Payment;

10
请注意,尽管函数名称可能会让人想起,但它的粒度比几天要高。这是很多天,但可以是零星的。
林德斯(Lindes)2012年

10
请记住,julianday返回“天”的(分数)数字,即24小时制,从开始日期的UTC 中午开始。除非您恰好在格林威治以西居住12个小时,否则通常不需要这些。例如,如果您住在伦敦,则今天上午与昨天下午的同一个星期五。
朱利安·席姆斯(JulianSymes)2013年

2
如果您使用的DateCreated是UTC,它会起作用。相反,如果是当地时间,则必须转换julianday('now')为当地时间。我找不到任何有此信息的地方。如果您确实julianday('now') - julianday(DateCreated)喜欢这篇文章,建议使用本地时间存储日期,则您的答案将因与格林尼治标准时间的抵触而偏离,并且是错误的。虽然可能不是将日期存储在本地时间的最佳做法,但它仍然可能在时区无关紧要的应用程序中发生(除非您使用的工具将日期强制显示在您身上)。
vapcguy

3
假设DateCreated位于本地时间(如果您这样做)julianday('now') - julianday(DateCreated, 'utc'),则要同时创建两个UTC,则它的工作方式与方法不同julianday('now', 'localtime') - julianday(DateCreated)。前者不计入夏令时,而是会在3月至11月为创建的日期增加一个小时。后者确实可以解决这个问题。stackoverflow.com/questions/41007455/...
vapcguy

59

天数差异

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) As Integer)

时差

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 As Integer)

分钟差异

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 As Integer)

差异秒

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 * 60 As Integer)

1
对于sqlite版本3.12.0,强制转换表达式的括号内为AS TYPE。例如“选择转换(5.6作为整数);” sqlite.org/lang_expr.html#castexpr否则,确实是有用的示例。

谢谢@rob。有人提议像以前那样编辑我。但是,当我在Sqlitebrowser中尝试时,它无法正常工作。也许是因为版本较旧。所以我保持原样..
Sayka '16

我只是使用SQLitebrowser并提到了错误抢劫。我可以将您的帖子编辑成现代措辞吗?
Noumenon

@Noumenon,请提出您的修改。我将在此处的sqlitebrowser中对其进行检查,如果可行,肯定会批准您的编辑。感谢您的时间。
塞卡(Sayka)2016年

2
该答案比公认的答案恕我直言更具特色。
马库斯·帕森斯

33

这两个答案都提供了所需的解决方案,但有些复杂。假设付款创建于January 6, 2013。我们想知道今天和今天之间的区别。

sqlite> SELECT julianday() - julianday('2013-01-06');
34.7978485878557 

相差34天。我们可以使用julianday('now')更好的清晰度。换句话说,我们不需要将 date()datetime()函数作为参数来julianday() 起作用。


我不确定,但是如果此命令在代码中,并且值Jan 6 2013来自数据库,则需要考虑使用的数据类型。
NoChance

23

SQLite文档是一个很好的参考,DateAndTimeFunctions页面是一个很好的书签。

记住,使用sqlite命令行实用程序处理查询非常容易:

sqlite> select julianday(datetime('now'));
2454788.09219907
sqlite> select datetime(julianday(datetime('now')));
2008-11-17 14:13:55

1
由于此页面带有Google搜索引擎排名,因此,此处是当前链接:sqlite.org/lang_datefunc.html
markusN

9

这个答案有点冗长,文档不会告诉您(因为他们假设您将日期作为UTC日期存储在数据库中),但是此问题的答案很大程度上取决于存储日期的时区您也不必使用Date('now'),而是使用julianday()函数来计算两个日期相对于一个公共日期的时间,然后彼此减去这些结果的差。

如果您的日期存储在UTC中:

SELECT julianday('now') - julianday(DateCreated) FROM Payment;

这是排名最高的答案,并且在文档中。如果您问我,那只是图片的一部分,而且答案很简单。

如果您的日期存储在本地时间,使用上面的代码会让你的答案的小时数你的GMT偏移。如果您和我一样在美国东部,即GMT -5,那么您的结果将增加5个小时。并且,如果您DateCreated因为julianday('now')违反格林尼治标准时间而尝试符合UTC :

SELECT julianday('now') - julianday(DateCreated, 'utc') FROM Payment;

这有一个错误,它将DateCreated在夏令时(3月至11月)期间增加一个小时。假设“现在”是非DST的一天中午,并且您在6月(DST期间)中午创建了一些东西,则小时数部分将相隔1小时而不是0小时。您必须在应用程序的代码中编写一个显示结果的函数,以修改结果并从DST日期中减去一个小时。我这样做了,直到意识到有个更好的解决方案: SQLite vs. Oracle-计算日期差-小时

相反,正如我所指出的,对于本地时间存储的日期,请将两者都与本地时间匹配:

SELECT julianday('now', 'localtime') - julianday(DateCreated) FROM Payment;

或附加'Z'到当地时间:

julianday(datetime('now', 'localtime')||'Z') - julianday(CREATED_DATE||'Z')

这两个似乎都可以补偿并且不为DST日期添加额外的小时数,而是直接相减-因此,在DST日的正午创建的项目在非DST的正午检查时将不会获​​得额外的小时。执行计算。

而且,尽管我认识到大多数人会说不要在本地时间将日期存储在数据库中,而要在UTC中存储日期,这样您就不会遇到这种情况,但是并不是每个应用程序都具有全世界的受众,也不是每个程序员都想要进行系统中每个日期到UTC的转换,并在他们每次在数据库中执行GET或SET时再次返回,并弄清楚是本地还是UTC。


“这只是图片的一部分,如果你问我的话,答案很简单。” 是啊,你说得对。但是,两年后,当您提出问题时,他问了问题3分钟后,我给了我答复。很简单,但她似乎适合他。
弗雷德(Fred)

1
@Fred公平。但是实际上,就像我上面描述的那样,最终却带我去兜风,所以对我没有帮助。我想确保将来看到此消息的任何人都确切地知道正在发生的事情,因此他们不会遇到与我一样的陷阱-或者,如果这样做,他们将知道如何摆脱困境。
vapcguy

@Fred,这是一个很好的解释,我不确定会发生什么?也许发布您的答案?
NoChance

感谢您的解释。我不确定SQLite的人们决定违背人们多年来接受的标准,最终导致不必要的复杂实现并且很难在诸如日期和时间等关键方面进行测试!想象一下,验证应用程序中每个日期的正常工作所需的测试用例数量,就像人们期望的那样!
NoChance

3

只是编写时钟功能的注释。对于那些寻找工作时间的人来说,这是一个非常简单的更改,即小时数和分钟数显示为大多数工资公司希望的百分比60。

CAST ((julianday(clockOUT) - julianday(clockIN)) * 24 AS REAL) AS HoursWorked

Clock In            Clock Out           HoursWorked
2016-08-07 11:56    2016-08-07 18:46    6.83333332836628

整洁的小查询,尽管如此:)
vapcguy


2

假设您的日期格式如下:“ YYYY-MM-DD HH:MM:SS”,如果您需要查找两个日期之间的月数差:

(strftime('%m', date1) + 12*strftime('%Y', date1)) - (strftime('%m', date2) + 12*strftime('%Y', date2))


2

首先,不清楚您的日期格式是什么。已经有一个涉及的答案strftime("%s")

我喜欢扩展这个答案。

SQLite仅具有以下存储类:NULL,INTEGER,REAL,TEXT或BLOB。为了简化起见,我将假设日期是实数,其中包含自1970-01-01开始的秒数。这是一个示例架构,我将在其中放入“ 2018年12月1日”的示例数据:

CREATE TABLE Payment (DateCreated REAL);
INSERT INTO Payment VALUES (strftime("%s", "2018-12-01"));

现在,让我们计算出“ 2018年12月1日”与现在之间的日期差(在我写这篇文章时,它是2018年12月12日中午):

日期差(天):

SELECT (strftime("%s", "now") - DateCreated) / 86400.0 FROM Payment;
-- Output: 11.066875

日期差(小时):

SELECT (strftime("%s", "now") - DateCreated) / 3600.0 FROM Payment;
-- Output: 265.606388888889

日期差异(以分钟为单位):

SELECT (strftime("%s", "now") - DateCreated) / 60.0 FROM Payment;
-- Output: 15936.4833333333

日期差异(以秒为单位):

SELECT (strftime("%s", "now") - DateCreated) FROM Payment;
-- Output: 956195.0

2

如果您想以秒为单位

SELECT strftime('%s', '2019-12-02 12:32:53') - strftime('%s', '2019-12-02 11:32:53')


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.