如果你的
DateTime
是以UTC格式存在,而你希望将其转换到其他时区,你可以使用
withZone
方法进行转换。
对于下面的例子,我的默认时区是
America/Sao_Paulo
(你可以使用
DateTimeZone.getDefault()
来检查你的时区):
DateTime mStartDate = DateTime.now(DateTimeZone.UTC).withTimeAtStartOfDay();
System.out.println(mStartDate);
System.out.println(mStartDate.withZone(DateTimeZone.getDefault()));
输出结果为:
2017-06-13T00:00:00.000Z
2017-06-12T21:00:00.000-03:00
请注意,
withZone
方法将日期和时间正确转换为我的时区(在
America/Sao_Paulo
中当前偏移量为
UTC-03:00
),因此已相应地进行了调整。
如果您只想获取时间(小时/分钟/秒),可以使用
toLocalTime()
方法:
System.out.println(mStartDate.withZone(DateTimeZone.getDefault()).toLocalTime())
输出结果为:
21:00:00.000
如果您需要其他格式(例如,不打印毫秒的3个数字),您可以使用
DateTimeFormatter
。好处在于您可以在格式化程序中设置时区,因此无需转换
DateTime
:
DateTimeFormatter fmt = DateTimeFormat.forPattern("HH:mm:ss").withZone(DateTimeZone.getDefault());
System.out.println(fmt.print(mStartDate));
输出结果如下:
21:00:00
要获取您的范围,您可以使用上述其中一种方法与您的DateTime(mStartDate和mEndDate)一起使用,并使用DateTimeFormatter将其更改为所需的任何格式。
PS:我认为您在使用getMillis()时忽略了一点,即两个日期时间(在UTC和默认时区中)表示相同的瞬间。 您只是将此瞬间转换为本地时间,但是毫秒数是相同的(请考虑一下,现在,在这个时刻,世界上每个人都处于相同的瞬间(相同的毫秒数),但是他们的本地时间可能因所在地不同而有所不同)。 因此,当将UTC DateTime转换为另一个时区时,我们只是找到对应于相同毫秒数的该区域的本地时间。
您可以使用两个对象上的getMillis()方法进行检查。
System.out.println(mStartDate.getMillis())
System.out.println(mStartDate.withZone(DateTimeZone.getDefault()).getMillis())
请注意,即使我将对象转换为另一个时区,毫秒数仍然相同(
1497312000000
)。这是因为两者表示相同的瞬间,我只是将它们移动到另一个本地时间不同的时区。
Java新日期/时间API
Joda-Time已经停止使用并被新API取代,因此我不建议使用它开始新项目。如果您的情况是这样的,可以考虑使用新的日期/时间API,但如果您有一个使用Joda的大型代码库或者现在不想迁移它,则可以忽略余下的答案。
无论如何,即使在
joda网站上也指出:“请注意,Joda-Time被认为是一个基本完成的项目。没有计划进行重大增强。如果使用Java SE 8,请迁移到java.time(JSR-310)。”。*
如果您使用的是
Java 8,请考虑使用
新的java.time API。它比旧API更易于使用,
更少出错且容错性更好。我不确定它是否已经适用于所有Android版本(但请参见下面的替代方案)。
如果您使用的是
Java <= 7,则可以使用
ThreeTen Backport,这是Java 8新日期/时间类的一个很好的后移版本。对于
Android,有一种方法可以使用它,即使用
ThreeTenABP(有关如何使用它的更多信息,请单击
此处)。
下面的代码适用于两者。唯一的区别是包名称(在Java 8中为
java.time
,在ThreeTen Backport(或Android的ThreeTenABP)中为
org.threeten.bp
),但类和方法
名称相同。
要获取UTC当天开始时的当前日期,您可以执行以下操作:
// UTC's today at start of the day
ZonedDateTime utc = LocalDate.now(ZoneOffset.UTC).atStartOfDay(ZoneOffset.UTC);
System.out.println(utc); // 2017-06-13T00:00Z
首先,我使用
LocalDate.now(ZoneOffset.UTC)
寻找在 UTC 时区下的当前本地日期。如果我只使用
LocalDate.now()
,它会获取我的默认时区下的当前日期,这不是我们想要的(根据你所在的地点和默认时区,它可能与 UTC 不同)。
然后我使用
atStartOfDay(ZoneOffset.UTC)
来获取 UTC 下当天的开始时间。我知道两次使用 UTC 听起来有些多余,但是 API 允许我们在此方法中使用任何时区,并且在我看来,这使得我们想要哪个时区变得明确了(如果日期处于具有夏令时更改的时区中,则一天的开始时间可能不是午夜 - 时区参数是为了保证设置正确的值)。
输出结果为:
2017-06-13T00:00Z
要转换为我的默认时区,可以使用
ZoneId.systemDefault()
,在我的情况下返回
America/Sao_Paulo
。要进行转换并仅获取本地时间部分,只需执行:
System.out.println(utc.withZoneSameInstant(ZoneId.systemDefault()).toLocalTime()); // 21:00
输出结果为:
21:00
如果你想要更改输出格式,你可以使用一个格式化器:
// formatter for localtime (hour/minute/second)
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(fmt.format(utc.withZoneSameInstant(ZoneId.systemDefault()))); // 21:00:00
The output is:
21:00:00