从毫秒时间开始的Java日期转换

时间:2015-08-19 12:05:26

标签: java date calendar

我正在尝试计算给定日期的偏移时间。我把日期作为一个字符串并解析它,我有毫秒的偏移量。例如,

日期: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;
}

如果有人看到我做错了或有更简单的方法,我会很感激帮助。谢谢!

2 个答案:

答案 0 :(得分:2)

Calendar的毫秒数以UTC时区到达,但您使用默认时区实例化日历,这是您的本地时区。这会为您的结果增加额外的时间。

要解决此问题,请使用UTC时区创建Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 实例:

@users = User.joins(:account)

答案 1 :(得分:0)

TL;博士

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

现代方法使用 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

您的输入字符串几乎符合日期时间格式的ISO 8601标准。在解析/生成字符串时, java.time 类默认使用标准格式。

将您的字符串转换为合规。用T替换中间的空格。

String input = "2015-08-18 00:00:00".replace( " " , "T" ) ;
  

2015-08-18T00:00:00

LocalDateTime

将您的输入解析为LocalDateTime,因为您的输入缺少offset-from-UTCtime 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.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance 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的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore