为什么我的Java Calendar.setTime()偶尔会设置错误的时间?
使用下面的代码,我注意到有时日期格式不正确。更奇怪的是,有时时间戳会有正确的日期,而时间戳副本会有错误的日期,反之亦然为什么我的Java Calendar.setTime()偶尔会设置错误的时间?,java,gregorian-calendar,java.util.date,java.util.calendar,Java,Gregorian Calendar,Java.util.date,Java.util.calendar,使用下面的代码,我注意到有时日期格式不正确。更奇怪的是,有时时间戳会有正确的日期,而时间戳副本会有错误的日期,反之亦然 public static Timestamp method(String date, DateFormat dateFormat) throws Exception { // date is always "2017-02-17" // original GregorianCalenda
public static Timestamp method(String date, DateFormat dateFormat) throws Exception {
// date is always "2017-02-17"
// original
GregorianCalendar gCal = new GregorianCalendar();
gCal.setTime(dateFormat.parse(date));
Timestamp timeStamp = new Timestamp(gCal.getTimeInMillis());
// copy
GregorianCalendar gCalCopy= new GregorianCalendar();
gCalCopy.setTime(dateFormat.parse(date));
Timestamp timeStampCopy = new Timestamp(gCalCopy.getTimeInMillis());
if (!timeStamp.toString().contains("2017-02-17"))
System.out.println(timeStamp.toString());
if (!timeStampCopy.toString().contains("2017-02-17"))
System.out.println(timeStampCopy.toString());
return timeStamp;
}
我不确定是什么原因导致了它,但我尝试了使用日期对象,并且遇到了相同的问题。我认为这可能是一个解析问题,但由于它做了两次相同的事情,我不确定
下面是我得到的一些值:
timeStamp is: 2017-02-17 00:00:00.0
timeStampCopy is: 1700-02-17 00:00:00.0
您说您正在线程之间共享DateFormat实例 根据报告: 日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一种格式,则必须在外部对其进行同步 请注意,这是指对DateFormat实例的访问的外部同步,而不是方法。只有在DateFormat实例没有其他用途的情况下,同步该方法才能解决此问题 您可以: 使用DateFormat实例显式同步所有代码值得在变量中添加@GuardeBy注释,以便在使用它之前记录您希望持有的锁; 将变量类型更改为ThreadLocal,并适当初始化共享变量,这确保每个线程都有自己的DateFormat副本。 后一种方法具有较低的争用,因为每个线程都可以独立于其他线程进行。这也意味着您不能意外地忽略同步
但是,有更好的库来处理日期和时间,这些库是在事后考虑到诸如DateFormat缺乏线程安全性等问题而设计的。在Java8中,有Java.time API;对于Java的早期版本,有Jodatime。您说您正在线程之间共享DateFormat实例 根据报告: 日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一种格式,则必须在外部对其进行同步 请注意,这是指对DateFormat实例的访问的外部同步,而不是方法。只有在DateFormat实例没有其他用途的情况下,同步该方法才能解决此问题 您可以: 使用DateFormat实例显式同步所有代码值得在变量中添加@GuardeBy注释,以便在使用它之前记录您希望持有的锁; 将变量类型更改为ThreadLocal,并适当初始化共享变量,这确保每个线程都有自己的DateFormat副本。 后一种方法具有较低的争用,因为每个线程都可以独立于其他线程进行。这也意味着您不能意外地忽略同步 但是,有更好的库来处理日期和时间,这些库是在事后考虑到诸如DateFormat缺乏线程安全性等问题而设计的。在Java8中,有Java.time API;对于Java的早期版本,有Jodatime。是正确的,应该接受 时间是线程安全的 time类通过使用不可变对象并使其具有固有的线程安全性来解决这个问题
LocalDate ld = LocalDate.of( "2017-02-17" );
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ld.atStartOfDay( z );
通过调用toString以标准格式生成字符串。对于其他格式,请使用类。搜索堆栈溢出以获取许多示例和讨论。不用担心线程,所有线程都是安全的
对于UTC格式的值,请提取一个
不需要使用java.sql.Timestamp。现代JDBC驱动程序可以通过toObject和setObject方法处理java.time类型。对于旧驱动程序,使用添加到旧类的新方法进行转换
关于java.time
该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&
该项目现已启动,建议迁移到类
要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是
从哪里获得java.time类
后来
内置的。
标准JavaAPI的一部分,带有捆绑实现。
Java9添加了一些次要功能和修复。
和
大部分java.time功能都在中向后移植到Java6和Java7。
该项目特别针对Android采用了上述Three-Ten Backport。
看见
该项目使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。您可以在这里找到一些有用的类,如、、和。是正确的,应该接受
时间是线程安全的
time类通过使用不可变对象并使其具有固有的线程安全性来解决这个问题
LocalDate ld = LocalDate.of( "2017-02-17" );
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ld.atStartOfDay( z );
通过调用toString以标准格式生成字符串。对于其他格式,请使用类。海
rch堆栈溢出的许多例子和讨论。不用担心线程,所有线程都是安全的
对于UTC格式的值,请提取一个
不需要使用java.sql.Timestamp。现代JDBC驱动程序可以通过toObject和setObject方法处理java.time类型。对于旧驱动程序,使用添加到旧类的新方法进行转换
关于java.time
该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&
该项目现已启动,建议迁移到类
要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是
从哪里获得java.time类
后来
内置的。
标准JavaAPI的一部分,带有捆绑实现。
Java9添加了一些次要功能和修复。
和
大部分java.time功能都在中向后移植到Java6和Java7。
该项目特别针对Android采用了上述Three-Ten Backport。
看见
该项目使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。您可以在这里找到一些有用的类,例如、、和。如果要在线程之间共享DateFormat实例,您的函数输入是什么?@AndyTurner是!由于某种原因,我刚想补充一下,当我将synchronized添加到方法中时,它似乎突然开始正常工作。我不知道为什么。我强烈建议不要使用遗留的java.util.Calendar和java.util.Date类。您应该认真考虑使用Java.Times包中最适合您的用例的类。这不是为了使该方法同步,而是确保对DATE格式的独占访问。目前,同步此方法可能会有所帮助,但只有在您开始在其他地方使用该DateFormat之前。您对函数的输入是什么?是否在线程之间共享DateFormat实例?@AndyTurner是!由于某种原因,我刚想补充一下,当我将synchronized添加到方法中时,它似乎突然开始正常工作。我不知道为什么。我强烈建议不要使用遗留的java.util.Calendar和java.util.Date类。您应该认真考虑使用Java.Times包中最适合您的用例的类。这不是为了使该方法同步,而是确保对DATE格式的独占访问。现在,同步这个方法可能会有所帮助,但只有在你开始在其他地方使用DateFormat之前。除了最后一句话,一切都很好。Joda Time项目现在处于维护模式,建议迁移到java.Time类。对于Java 6和7的早期版本,请使用项目。java.time的大部分功能都在那里进行了后移植。在项目中进一步适应Android。除了最后一句话,一切都很好。Joda Time项目现在处于维护模式,建议迁移到java.Time类。对于Java 6和7的早期版本,请使用项目。java.time的大部分功能都在那里进行了后移植。在项目中进一步适应Android。