令人困惑的问题
你的问题可能会使用一些重写.
如果我进行选择查询 – 您应该解释这个并给出确切的查询语句.
红鲱鱼
由于处理两个独立的服务器(数据库服务器,Web应用服务器),每个服务器都有不同的时区设置,因此您应该更清楚地分离问题.事实上,MySQL服务器似乎只是一个红色的鲱鱼,分散注意力.
您应该测试并报告实际时间,而不是谈论不相关的MySQL服务器.容易做…只是谷歌“当前时间在utc”.
因此,老水手的格言:使用一个指南针或三个,但从不两个.
时区
三个字母的时区代码已经过时,既不是标准化也不是唯一的.例如,“IST”表示“印度标准时间”和“爱尔兰标准时间”.
使用时区名称,如此slightly outdated list所示.在您的情况下,05:30,您可以在旧表中使用“Asia / Kolkata”,也称为“Asia / Calcutta”.这比UTC / GMT早5.5小时.
乔达时间
java.util.Date&正如你所看到的那样,日历类是非常糟糕和令人困惑的.避免他们.使用开源第三方Joda-Time或Java 8中的新java.time.* classes(受Joda-Time启发).
下面的代码在美国西海岸时区的Mac上使用Joda-Time 2.3和Java 8.
底线
让我们确定1389975349000L≈16:15UTC≈21:45印度.
正如问题所述,这与EpochConverter.com一致.
// Specify a time zone rather than depend on defaults.
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
long millis = 1389975349000L;
DateTime dateTimeUtc = new DateTime( millis, DateTimeZone.UTC );
DateTime dateTimeKolkata = dateTimeUtc.toDateTime( timeZoneKolkata );
转储到控制台……
System.out.println( "millis: " + millis );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeKolkata: " + dateTimeKolkata );
跑的时候……
millis: 1389975349000
dateTimeUtc: 2014-01-17T16:15:49.000Z
dateTimeKolkata: 2014-01-17T21:45:49.000+05:30
神秘数字
问题提到了第二个数字:1389955549000L.
这个数字与第一个数字的日期相同,时间不同.
让我们确定1389955549000L≈10:45UTC≈16:15印度.
long mysteryMillis = 1389955549000L;
DateTime mysteryUtc = new DateTime( mysteryMillis, DateTimeZone.UTC );
DateTime mysteryKolkata = mysteryUtc.toDateTime( timeZoneKolkata );
转储到控制台……
System.out.println( "mysteryMillis: " + mysteryMillis );
System.out.println( "mysteryUtc: " + mysteryUtc );
System.out.println( "mysteryKolkata: " + mysteryKolkata );
跑的时候……
mysteryMillis: 1389955549000
mysteryUtc: 2014-01-17T10:45:49.000Z
mysteryKolkata: 2014-01-17T16:15:49.000+05:30
结论
我不是百分百肯定,但……
→您的网络应用服务器计算机的时钟设置似乎不正确,设置为UTC时间而不是印度时间.
Web应用服务器显然是在印度时区的16:15时间,但显然在那一刻印度的真实时间是21:45.换句话说,时间与时区不匹配.
将UTC时间与非UTC时区混合=错误.
如果您设置印度时区,则设置印度时间以匹配.
细节
请注意,我们在两组数字中都有“16:15”.
java.util.Date类的设计非常糟糕,它本身没有时区信息但是在其toString实现中应用Java虚拟机的默认时区.这是避免此课程的众多原因之一,但可能是您的问题的关键.
得到教训
避免使用java.util.Date,java.util.Calendar和java.text.SimpleDateFormat类.仅在需要时与其他类交换值时使用.
使用Joda-Time或新的java.time.*类(JSR 310).
指定时区,永远不要依赖默认时区.
匹配每台服务器上的时区.通过谷歌搜索“utc中的当前时间”进行验证.
尽可能将主机服务器的操作系统时区设置为UTC或GMT.在某些操作系统上没有这样的选择,因此选择“大西洋/雷克雅未克”作为解决方法,因为冰岛全年保持在UTC / GMT,没有任何夏令时时间的废话.
不要通过调用TimeZone.setDefault来设置JVM的默认时区(在最坏情况下作为最后的手段除外).设置默认值是粗鲁的,因为它会立即影响该JVM中运行的所有应用程序中所有线程中的所有代码.并且它是不可靠的,因为任何其他代码都可以在运行时在您的应用程序上更改它.而是在所有日期时间代码中指定时区.永远不要隐含地依赖JVM的当前默认值. Joda-Time和java.time都有采用时区参数的方法.因此,虽然将所有服务器计算机的“主机操作系统”时区设置为UTC是一种很好的做法,但您不应该依赖于Java代码中的那个.