以下问题困扰着我,我找不到任何合理的解释和解决方案。也许有人可以启发我。
我有一个应用程序,用于计算日期差异(以天为单位) - 在“搜索”掩码和“详细信息”掩码中。在第一个掩码中,我使用天来过滤掉具有持续时间搜索条件(搜索掩码)的记录,并使用SQL查询执行此操作:
WHERE...
...
AND DECODE(TRUNC(to_number(SUBSTR((close_date -
create_date),1,instr(close_date - create_date,' ')))), NULL,
TRUNC(to_number(SUBSTR((systimestamp - create_date),1,instr(systimestamp -
create_date,' ')))), TRUNC(to_number(SUBSTR((close_date -
create_date),1,instr(close_date - create_date,' ')))) ) >=140
AND DECODE(TRUNC(to_number(SUBSTR((close_date -
create_date),1,instr(close_date - create_date,' ')))), NULL,
TRUNC(to_number(SUBSTR((systimestamp - create_date),1,instr(systimestamp -
create_date,' ')))), TRUNC(to_number(SUBSTR((close_date -
create_date),1,instr(close_date - create_date,' ')))) ) <=140
在这种特殊情况下,我试图查找持续时间为140天的所有记录。
在第二个掩码(详细信息)中,我显示记录详细信息,包括其持续时间。这是通过以下java代码完成的:
public static Integer getDuration(Date caseDate, Date closeDate) {
Date beginDate = caseDate;
Date endDate = (closeDate != null)? closeDate: new Date();
long difference = endDate.getTime() - beginDate.getTime();
int daysDiff = (int) (difference / (24.0 * 60 * 60 * 1000));
return new Integer(daysDiff);
}
我的问题是,当我搜索时,我会找到一些与搜索条件相对应的记录。例如,我找到4条记录,所有记录的持续时间为140天。这是根据Oracle的说法。但是当我为其中一些打开详细信息掩码时,我会得到139天的持续时间。所以Java和Oracle以某种方式以不同的方式计算日期差异。似乎在Oracle中正在进行一些舍入,但我找不到发生这种情况的地方。所以任何建议都会有所帮助。谢谢!
电贺, almaak
答案 0 :(得分:3)
日期可能相同,但时间可能不同。通过毫秒计算得出139天。 (Java)的
我建议不要使用millis,而是使用天数计算。
像
这样的东西public long daysBetween(Calendar startDate, Calendar endDate) {
Calendar date = (Calendar) startDate.clone();
long daysBetween = 0;
while (date.before(endDate)) {
date.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}}
或
/**
*
* @param c1 from
* @param c2 to
* @return amount of days between from and to
*/
public int diff(Calendar c1, Calendar c2) {
int years = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
if (years == 0) {
return c2.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);
} else {
Calendar endOfYear = Calendar.getInstance();
endOfYear.set(Calendar.YEAR, c1.get(Calendar.YEAR));
endOfYear.set(Calendar.MONTH, 11);
endOfYear.set(Calendar.DAY_OF_MONTH, 31);
int days = endOfYear.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);
for (int i=1;i <years;i++) {
endOfYear.add(Calendar.YEAR, 1);
days += endOfYear.get(Calendar.DAY_OF_YEAR);
}
days += c2.get(Calendar.DAY_OF_YEAR);
return days;
}
}
旁注: 第一个例子比第二个例子略慢,但如果只是因为差异很小,那就是可以忽略的。
答案 1 :(得分:1)
我以相同的方式计算,但我使用dayDiff长度不是整数。所以也尝试一下,不要施展它。它应该工作正常。
答案 2 :(得分:1)
这里的问题是你认为两列都是DATE列,其中至少有两列是TIMESTAMP列。当您从另一个日期中提取一个日期时,您会得到一个数字。但是当你从时间戳中提取日期时,反之亦然,你得到一个INTERVAL。
一个例子
包含DATE和TIMESTAMP的表:
SQL> create table mytable (close_date,create_date)
2 as
3 select date '2010-11-01', systimestamp from dual union all
4 select date '2010-11-11', systimestamp from dual union all
5 select date '2010-12-01', systimestamp from dual
6 /
Table created.
SQL> desc mytable
Name Null? Type
----------------------------------------- -------- ----------------------------
CLOSE_DATE DATE
CREATE_DATE TIMESTAMP(6) WITH TIME ZONE
从DATE列中提取TIMESTAMP,导致INTERVAL:
SQL> select close_date - create_date
2 from mytable
3 /
CLOSE_DATE-CREATE_DATE
---------------------------------------------------------------------------
+000000130 11:20:11.672623
+000000140 11:20:11.672623
+000000160 11:20:11.672623
3 rows selected.
并且没有必要摆弄TO_NUMBER和SUBSTR。只需使用EXTRACT函数从间隔中获取所需的组件:
SQL> select extract(day from (close_date - create_date))
2 from mytable
3 /
EXTRACT(DAYFROM(CLOSE_DATE-CREATE_DATE))
----------------------------------------
130
140
160
3 rows selected.
此致 罗布。
这是一个有两个TIMESTAMPS的示例,它显示INTERVAL是截断的,而不是舍入的:
SQL> create table mytable (close_date,create_date)
2 as
3 select to_timestamp('2010-11-01','yyyy-mm-dd'), trunc(systimestamp,'dd') + interval '6' hour from dual union all
4 select to_timestamp('2010-11-11','yyyy-mm-dd'), trunc(systimestamp,'dd') + interval '12' hour from dual union all
5 select to_timestamp('2010-12-01','yyyy-mm-dd'), trunc(systimestamp,'dd') + interval '18' hour from dual
6 /
Table created.
SQL> desc mytable
Name Null? Type
----------------------------------------- -------- ----------------------------
CLOSE_DATE TIMESTAMP(9)
CREATE_DATE DATE
SQL> select close_date - create_date
2 from mytable
3 /
CLOSE_DATE-CREATE_DATE
---------------------------------------------------------------------------
+000000130 18:00:00.000000000
+000000140 12:00:00.000000000
+000000160 06:00:00.000000000
3 rows selected.
SQL> select extract(day from (close_date - create_date))
2 from mytable
3 /
EXTRACT(DAYFROM(CLOSE_DATE-CREATE_DATE))
----------------------------------------
130
140
160
3 rows selected.