mysql和java中的时区差异

mysql和java中的时区差异,java,mysql,timezone,convert-tz,Java,Mysql,Timezone,Convert Tz,我在mysql中有一个查询,它比较了两个类似这样的日期 convert_tz(updatedDate,'+05:30','-05:00') < ? pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis())); rs=pst.executeQuery(); System.out.println("=====new Open Tickets Query

我在mysql中有一个查询,它比较了两个类似这样的日期

convert_tz(updatedDate,'+05:30','-05:00') < ?
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));

                rs=pst.executeQuery();
                System.out.println("=====new Open Tickets Query executed=====");
                System.out.println(pst);
product    count
-------    ------
    A        155
    B        19
现在,我在java中使用这样的PreparedStatement进行设置

convert_tz(updatedDate,'+05:30','-05:00') < ?
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));

                rs=pst.executeQuery();
                System.out.println("=====new Open Tickets Query executed=====");
                System.out.println(pst);
product    count
-------    ------
    A        155
    B        19
最后一行打印整个查询,值集为

convert_tz(updatedDate,'+05:30','-05:00') < '2013-04-14 09:30:00'
所以,我怀疑我把代码改成了时区问题

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);
但它仍然给出了同样的错误结果

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

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

另外,对于我尝试使用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()));
更新:- 如果我使用不推荐的方法,答案是正确的

 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));
更新2:- 在第一个答案的建议之后,我这样做了

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

2) 执行

System.out.println(new Date(System.currentTimeMillis()));
输出:
Mon Apr 22 11:56:25 IST 2013


表示两个系统具有相同的时区

哪个值是从您的
时区.getDefault().getID()
和MySQL默认时区返回的

顺便说一句,您可以尝试使用如下实用程序跨时区转换日期时间:

public Calendar convertDateToServerTimeZone(Date dateTime, String timeZone) {
    Calendar userDefinedTime = Calendar.getInstance();
    userDefinedTime.setTime(dateTime);
    if(!TimeZone.getDefault().getID().equalsIgnoreCase(timeZone)) {
    System.out.println        ("original defined time: " + userDefinedTime.getTime().toString() + " on tz:" + timeZone);
    Calendar quartzStartDate = new GregorianCalendar(TimeZone.getTimeZone(timeZone));
    quartzStartDate.set(Calendar.YEAR, userDefinedTime.get(Calendar.YEAR));
    quartzStartDate.set(Calendar.MONTH, userDefinedTime.get(Calendar.MONTH));
    quartzStartDate.set(Calendar.DAY_OF_MONTH, userDefinedTime.get(Calendar.DAY_OF_MONTH));
    quartzStartDate.set(Calendar.HOUR_OF_DAY, userDefinedTime.get(Calendar.HOUR_OF_DAY));
    quartzStartDate.set(Calendar.MINUTE, userDefinedTime.get(Calendar.MINUTE));
    quartzStartDate.set(Calendar.SECOND, userDefinedTime.get(Calendar.SECOND));
    quartzStartDate.set(Calendar.MILLISECOND, userDefinedTime.get(Calendar.MILLISECOND));
    System.out.println("adapted time for " + TimeZone.getDefault().getID() + ": " + quartzStartDate.getTime().toString());
    return quartzStartDate;
    } else {
    return userDefinedTime;
    }
}
我在这里使用过此功能:


希望他的帮助。

如果看不到第二个查询中匹配的值,而不是第一个查询中匹配的值,就很难绝对确定。但有一点需要记住,时区与偏移量不同。请阅读本手册的“时区!=偏移量”部分

例如,您说您正在转换到
美国/纽约
时区。该区域有时为UTC-05:00(东部标准时间),有时为UTC-04:00(东部夏时制)。由于夏令时的-4偏移量,完全有可能正在拾取某些数据


当您硬编码到-5偏移量时,您没有考虑任何时区规则。这可以解释这种差异。

时区信息不会应用于日期/时间,除非您在连接URL中设置了useTimeZone=true。您还可以使用getTimestamp()方法,该方法将日历作为参数。

背景:即使是聪明的程序员也有一个令人惊讶的普遍误解,即存储的时间戳(在数据库中、日期、日历、时间戳等)以某种方式具有时区信息它们没有。时间戳(至少在Java 8之前)存储为UTC 1970年1月1日午夜后的毫秒数。句末。设置时区所做的唯一事情就是向计算机提供足够的信息,以便将时间戳转换为人类可读的格式,反之亦然

回答:当你怀疑这是一个时区问题时,你是对的。但您用来验证这一点的代码也有一个问题:

end.setTimeZone(TimeZone.getTimeZone("America/New York"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));
setTimeZone
语句对存储在
end
中的时间没有影响,因为时间已经设置好了。只有当您在之后存储时间,并且使用日历中的一种方法将时间从人类可读的格式转换过来时(而不是
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()));

由于您现在使用的方法可以转换为或转换为人类可读的格式,因此会使用指定的时区信息,因此似乎不起作用。然而,这只是掩盖了真正的问题。真正的问题是,当您从
endString
解析时间时,时间转换不正确。也就是说,
endString
表示的时区与解析日期时在
df1
中设置的时区不匹配

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

end.setTime(df1.parse(endString));
您需要:

  • 找出
    endString
    中的时间表示为哪个时区
  • df1
    not
    end
    设置为同一时区。因为
    df1
    是从人类格式转换日期的东西,所以使用的是时区信息

干杯

试试看。

按现在的设置设置时间戳参数

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

在数据库调用期间,JDBC驱动程序可能已经将输入的日期/时间值转换为GMT。因此,数据库正在处理的日期值不必考虑输入日期的时区,这可能会因客户端而异

而不是将_tz的设置为“+05:30”

convert_tz(updatedDate,'+05:30','-05:00')
从_tz将设置为'00:00'

convert_tz(updatedDate,'00:00','-05:00') 

我认为这里没有时区问题。因为当我使用不推荐的方法时,它工作得很好。当我直接在查询中输入日期时,结果是正确的。我认为MySQL的时区不是问题所在。MySQL的时区信息仅在处理将时间从/转换为文本的任务时使用。由于Bhavik在一个准备好的语句中作为参数传递时间,因此它已经被转换。如果Bhavik将时间作为文本直接放在查询中,那么MySQL的区域信息将被用来解析它。看我的答案。即使这样,它也不会影响时间的存储方式。它只对时间的显示/解析方式产生影响。“看我的答案。”马特·约翰逊也提出了一个很好的观点。在所有从文本转换时间的地方,确保使用的是基于位置的时区,而不是偏移(“America/New York”而不是“EST”)。MySQL的时区信息与您的问题无关,因为MySQL没有处理解析时间的工作
convert_tz(updatedDate,'00:00','-05:00')