我正在尝试计算给定日期的偏移时间。我把日期作为一个字符串并解析它,我有毫秒的偏移量。例如,
日期:2015-08-18 00:00:00
偏移时间:2678400000,当应用于该日期时,它等于2015-09-18 00:00:00,31天后。
我的目标是将每个偏移量(年/月/日/小时/分钟/秒)存储在数组中,以便稍后使用。 但是,当我使用Calendar类运行此计算时,由于某种原因,我在使用offsetConverter(2678400000)调用时需要额外的时间
Output: 0 years 0 months 31 days 19 hours 0 minutes 0 seconds
以下是我在此链接Best way to convert Milliseconds to number of years, months and days
中稍微找到并修改的代码 public static int[] offsetConverter(long offset) {
int[] delay = new int[6];
//delay 0-3 = years/months/days/seconds
Calendar c = Calendar.getInstance();
c.setTimeInMillis(offset);
delay[0] = c.get(Calendar.YEAR) - 1970;
delay[1] = c.get(Calendar.MONTH);
delay[2] = c.get(Calendar.DAY_OF_MONTH);
delay[3] = c.get(Calendar.HOUR_OF_DAY);
delay[4] = c.get(Calendar.MINUTE);
delay[5] = c.get(Calendar.SECOND);
for (int i = 0; i< delay.length; i++)
System.out.print(delay[i] + " ");
System.out.println();
return delay;
}
如果有人看到我做错了或有更简单的方法,我会很感激帮助。谢谢!
答案 0 :(得分:2)
Calendar
的毫秒数以UTC时区到达,但您使用默认时区实例化日历,这是您的本地时区。这会为您的结果增加额外的时间。
要解决此问题,请使用UTC时区创建Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
实例:
@users = User.joins(:account)
答案 1 :(得分:0)
LocalDateTime.parse(
"2015-08-18 00:00:00".replace( " " , "T" ) // Convert input string to comply with ISO 8601 standard format, replacing SPACE in the middle with a `T`.
).plus(
Duration.ofDays( 31 ) // If you meant ( 31 * 24-hours ).
// Period.ofDays( 31 ) // If you meant 31 calendar-days.
// Period.ofMonths( 1 ) // If you meant a calendar-month.
) // Returns a fresh `LocalDateTime` object, distinct from original, per Immutable Objects pattern.
.toString() // Generate a string in standard ISO 8601 format to textually represent this object’s value.
2015-09-18T00:00
这里的“偏移”一词是一个糟糕的术语选择。该词在日期时间处理中具有特定含义:时区与UTC的小时数,分钟数和秒数。请参阅UTC offset的维基百科条目。
您似乎更关心的是时间轴上没有附加时间。在 java.time 类中,如果以小时 - 分钟 - 秒为单位,则此类跨度称为Duration
,如果按年 - 月 - 天缩放,则称为Period
。
现代方法使用 java.time 类来取代麻烦的旧日期时间类,例如Date
/ Calendar
。
Duration
将您的时间跨度从毫秒数转换为Duration
对象。
Duration d = Duration.ofMillis( 2_678_400_000L );
这恰好是744小时。
d.toString():PT744H
出于好奇,我检查了744小时内的天数,如果我们将“天”定义为24小时的大块时间。
d.toDaysPart():31
所以看来你真的打算一个月或一个31天的时间。无论哪种方式,Java都有类。
如果你真的想要:(31 * 24小时),那么请使用Duration
。但是使用更多自我记录代码构造Duration
对象。
Duration d = Duration.ofDays( 31 ) ; // Exact same effect as `Duration.ofMillis( 2_678_400_000L )` but more clear as to your intention.
您的输入字符串几乎符合日期时间格式的ISO 8601标准。在解析/生成字符串时, java.time 类默认使用标准格式。
将您的字符串转换为合规。用T
替换中间的空格。
String input = "2015-08-18 00:00:00".replace( " " , "T" ) ;
2015-08-18T00:00:00
LocalDateTime
将您的输入解析为LocalDateTime
,因为您的输入缺少offset-from-UTC或time zone的指示。
LocalDateTime ldt = LocalDateTime.parse( input ) ;
ldt.toString():2015-08-18T00:00
添加您的Duration
对象以获得新的LocalDateTime
。 java.time 类使用immutable objects,因此原始对象保持不变。
LocalDateTime thirtyOneTimes24HoursLaterLdt = ldt.plus( d ) ; // Adding a span-of-time to our `LocalDateTime` object to get another `LocalDateTime` object.
thirtyOneTimes24HoursLaterLdt.toString():2015-09-18T00:00
请注意,LocalDateTime
不代表实际时刻,即时间轴上的特定点。如果没有时区或从UTC偏移的背景,那么对于大约26-27小时范围内的潜在时刻只是一个粗略的想法。
ZonedDateTime
如果您确定输入字符串是为了表示特定区域中的片刻,请应用ZoneId
来获取ZonedDateTime
对象(实际时刻)。
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ; // Now we have determined an actual moment, a point on the timeline.
zdt.toString():2015-08-18T00:00 + 12:00 [太平洋/奥克兰]
如果您不关心日期(日历上的整天),则可以添加Duration
。
ZonedDateTime thirtyOneTimes24HoursLaterZdt = zdt.plus( d ) ;
thirtyOneTimes24HoursLaterZdt.toString():2015-09-18T00:00 + 12:00 [太平洋/奥克兰]
如果您的业务逻辑确实是在日历上的三十一天,请使用Period
。
ZonedDateTime thirtyOneDaysLater = zdt.plus( Period.ofDays( 31 ) ) ;
threeOneDaysLater.toString():2015-09-18T00:00 + 12:00 [太平洋/奥克兰]
如果您的业务逻辑确实打算使用日历月而不是特定天数,请使用其他Period
。该课程根据需要进行调整,以处理不同月份的长度(read the doc并跟随that doc’s link)。
ZonedDateTime monthLater = zdt.plus( Period.ofMonths( 1 ) ) ;
monthLater.toString():2015-09-18T00:00 + 12:00 [太平洋/奥克兰]
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
使用符合JDBC driver或更高版本的JDBC 4.2,您可以直接与数据库交换 java.time 对象。不需要字符串也不需要java.sql。* classes。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。