确定Java线程中的日期时间(在Android中)的最佳方法是什么?
我有以下代码段:
public void repeatedlyPrintTheTime() {
final Handler handler = new Handler();
mR = new Runnable() {
public void run() {
System.out.println("Time 1 is " + mCalendar.getTime().toString());
System.out.println("Time 2 is " + GregorianCalendar.getInstance().getTime().toString());
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(mR, 1000);
}
时间1重复打印相同的时间,但每次迭代时间2都会更新。
每次我想检查时间是什么时,我是否真的需要获得GregorianCalendar的新实例?
答案 0 :(得分:2)
是的,每次要捕获当前时刻时,都必须获得一个新的日期时间对象实例。没有自动更新现有实例。
Instant.now()
GregorianCalendar
只有一个时刻,并且不会自动更新。如果它是自动更新的,那么你将永远无法做任何业务逻辑,因为随着代码的运行,值会不断变化!
此外,GregorianCalendar
及其兄弟类非常混乱,应该避免。它们现在已经遗留下来,取而代之的是java.time类。
以UTC为当前时刻使用Instant
。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
Instant instant = Instant.now();
instant.toString():2017-02-27T14:48:58.664Z
要稍后再次捕获当前时间,请获取另一个Instant
实例。
Instant instantLater = Instant.now();
instantLater.toString():2017-02-27T14:49:02.164Z
您甚至可以捕获它们之间的增量,作为Duration
对象。
Duration duration = Duration.between( instant, instantLater );
duration.toString():PT3.5S
要通过特定区域wall-clock time的镜头看到同一时刻,请调整为时区。应用ZoneId
获取ZonedDateTime
对象。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
zdt.toString():2017-02-27T09:48:58.664-05:00 [美国/蒙特利尔]
请参阅此code run live at IdeOne.com。
要表示未来或过去的时刻,请指定输入以获取OffsetDateTime
或ZonedDateTime
。
...的JavaDoc
ZonedDateTime.of(int year,int month,int dayOfMonth,int hour,int minute,int second,int nanoOfSecond,ZoneId zone)
ZonedDateTime zdt = ZonedDateTime.of( 2017 , 1 , 23 , 12 , 34 , 56 , 123456789 , ZoneId.of( "America/Montreal" );
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& 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。
答案 1 :(得分:0)
某些日历类不是线程安全的。您可以使用锁定在synchronized
块中插入该代码:
private Object calendarLock; --Class attribute
public void repeatedlyPrintTheTime() {
final Handler handler = new Handler();
mR = new Runnable() {
public void run() {
synchronized(calendarLock) {
System.out.println("Time 1 is " + mCalendar.getTime().toString());
System.out.println("Time 2 is " + GregorianCalendar.getInstance().getTime().toString());
handler.postDelayed(this, 1000);
}
}
};
handler.postDelayed(mR, 1000);
}