TimeZone在mysql和java中的差异

Bha*_*hah 7 java mysql timezone convert-tz

我在mysql中有一个查询,比较这样的2个日期

convert_tz(updatedDate,'+05:30','-05:00') < ?
Run Code Online (Sandbox Code Playgroud)

convert函数返回美国时间中createddate列的值.当我在mysql查询浏览器中运行此查询时

convert_tz(updatedDate,'+05:30','-05:00') < '2013-04-14 09:30:00'
Run Code Online (Sandbox Code Playgroud)

例如,它给了我正确的值

product    count
-------    ------
    A        123
    B        7
Run Code Online (Sandbox Code Playgroud)

现在,我正在使用像这样的PreparedStatement在java中设置它

pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));

                rs=pst.executeQuery();
                System.out.println("=====new Open Tickets Query executed=====");
                System.out.println(pst);
Run Code Online (Sandbox Code Playgroud)

最后一行打印整个查询,值集是

convert_tz(updatedDate,'+05:30','-05:00') < '2013-04-14 09:30:00'
Run Code Online (Sandbox Code Playgroud)

但它给了我不同的价值观

product    count
-------    ------
    A        155
    B        19
Run Code Online (Sandbox Code Playgroud)

所以,我怀疑是我将代码更改为TimeZone问题

end.setTimeZone(TimeZone.getTimeZone("America/New York"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));

                rs=pst.executeQuery();
                System.out.println("=====new Open Tickets Query executed=====");
                System.out.println(pst);
Run Code Online (Sandbox Code Playgroud)

但它仍然给出了同样错误的结果.

更多信息:我如何设置日历结束变量

我有一个Web应用程序,它给我日期字符串"2013-04-14 09:30:00"

            DateFormat df1=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                Calendar end=Calendar.getInstance();
                end.setTime(df1.parse(endString));
                end.set(Calendar.HOUR, 9);
                end.set(Calendar.MINUTE, 30);
                end.set(Calendar.SECOND, 0);
Run Code Online (Sandbox Code Playgroud)

另外,对于实验我尝试使用java.util.Date对象,它给我正确的结果以下是代码

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
end.setTime(sdf.parse("2012-10-01 00:00:00"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTime()));
Run Code Online (Sandbox Code Playgroud)

更新: - 如果我使用弃用方法,答案是正确的

 pst.setTimestamp(1, new java.sql.Timestamp(octDate.get(Calendar.YEAR)-1900,octDate.get(Calendar.MONTH),octDate.get(Calendar.DATE),octDate.get(Calendar.HOUR),octDate.get(Calendar.MINUTE),octDate.get(Calendar.SECOND),0));
pst.setTimestamp(2, new java.sql.Timestamp(end.get(Calendar.YEAR)-1900,end.get(Calendar.MONTH),end.get(Calendar.DATE),end.get(Calendar.HOUR),end.get(Calendar.MINUTE),end.get(Calendar.SECOND),0));
Run Code Online (Sandbox Code Playgroud)

更新2: - 在第一个回答的建议之后我做了这个

1)SELECT NOW()在mysql中执行并返回'2013-04-22 11:56:08'

2)执行

System.out.println(new Date(System.currentTimeMillis()));
Run Code Online (Sandbox Code Playgroud)

输出: Mon Apr 22 11:56:25 IST 2013

意味着两个系统都有相同的时区

Alv*_*son 6

背景:即使是出色的程序员也有一个令人惊讶的常见和大错误概念,即存储时间戳(在您的数据库中,日期,日历,时间戳等)以某种方式具有时区信息.他们不. 时间戳(直到Java 8,无论如何)被存储为自1970年1月1日午夜起的毫秒数.句末.设置时区的唯一方法是向计算机提供足够的信息以将该时间戳转换为人类可读格式,反之亦然.

答:当你怀疑这是一个时区问题时,你是对的.但是您用来尝试验证此代码的代码也存在问题:

end.setTimeZone(TimeZone.getTimeZone("America/New York"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));
Run Code Online (Sandbox Code Playgroud)

setTimeZone语句对存储的时间没有影响end,因为时间已经设置.如果您之后存储了时间,那么它只会产生影响,然后才会使用Calendar的一种方法,该方法将时间转换为人类可读的格式(而不是setTimeInMillis).

当您使用getTimeInMillis时间戳传递给准备好的语句时,您将直接检索时间戳.由于您没有将其转换为人格式,因此会再次忽略时区信息.

当你尝试

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
end.setTime(sdf.parse("2012-10-01 00:00:00"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTime()));
Run Code Online (Sandbox Code Playgroud)

pst.setTimestamp(1, new java.sql.Timestamp(octDate.get(Calendar.YEAR)-1900,octDate.get(Calendar.MONTH),octDate.get(Calendar.DATE),octDate.get(Calendar.HOUR),octDate.get(Calendar.MINUTE),octDate.get(Calendar.SECOND),0));
pst.setTimestamp(2, new java.sql.Timestamp(end.get(Calendar.YEAR)-1900,end.get(Calendar.MONTH),end.get(Calendar.DATE),end.get(Calendar.HOUR),end.get(Calendar.MINUTE),end.get(Calendar.SECOND),0));
Run Code Online (Sandbox Code Playgroud)

事情似乎有效,因为您现在正在使用转换为人类可读格式的方法,因此使用指定的时区信息.但是,这只是掩盖了真正的问题.真正的问题是,当您解析它时,时间被不正确地转换endString.也就是说,endString表示的时区df1与解析日期时设置的时区不匹配.

简短的回答:在这一行之前:

end.setTime(df1.parse(endString));
Run Code Online (Sandbox Code Playgroud)

你需要:

  • 找出时间endString表示的时区.
  • 设置df1不是 end同一时区.由于df1是从人格式转换日期的东西,它是使用的时区信息.

干杯!