使用下面的代码,我注意到有时日期格式不正确。为了使它变得更奇怪,有时timeStamp会有正确的日期,timeStampCopy会有错误的日期,反之亦然。
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;
}
我不确定是什么导致它但是我尝试使用Date对象并且遇到了同样的问题。我认为它可能是一个解析问题,但因为它做了两次相同的事情,我不确定。
以下是我得到的一些值:
timeStamp is: 2017-02-17 00:00:00.0
timeStampCopy is: 1700-02-17 00:00:00.0
答案 0 :(得分:3)
您说您正在线程之间共享DateFormat
实例。
根据Javadoc:
日期格式未同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问格式,则必须在外部进行同步。
请注意,这指的是对DateFormat
实例的访问的外部同步,不该方法。如果synchronized
实例没有其他用途,则方法DateFormat
只能解决此问题。
你可以:
DateFormat
实例显式同步所有代码(值得为变量添加@GuardedBy
注释,以便记录您希望在使用之前保留锁定;)< / LI>
ThreadLocal<DateFormat>
(并相应地初始化共享变量),这可确保每个线程都有自己的DateFormat
副本。后一种方法具有较低的争用,因为每个线程可以独立于其他线程继续进行。这也意味着您不会意外地省略同步。
但是,有更好的库来处理日期和时间,这些库是根据DateFormat
缺乏线程安全性等问题来设计的。在Java 8中,有java.time
API;对于早期版本的Java,有Jodatime。
答案 1 :(得分:1)
Answer by Turner是正确的,应该被接受。
java.time类通过使用不可变对象并使它们本身就是线程安全的来解决这个问题。
LocalDate ld = LocalDate.of( "2017-02-17" );
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ld.atStartOfDay( z );
通过调用toString
以标准ISO 8601格式生成字符串。对于其他格式,请使用DateTimeFormatter
类。搜索Stack Overflow以获取许多示例和讨论。不用担心线程,所有线程安全。
对于UTC中的值,请提取Instant
。
Instant instant = zdt.toInstant() ;
无需使用java.sql.Timestamp
。现代JDBC驱动程序可以通过toObject和setObject方法处理java.time类型。对于较旧的驱动程序,使用添加到旧类的新方法进行转换。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。