Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将java日期分解为小时_Java - Fatal编程技术网

将java日期分解为小时

将java日期分解为小时,java,Java,我在程序中收到以下开始日期和结束日期作为输入 2017-03-07 06:30:00至2017-03-07 11:35:00(yyyy-mm-dd hh:mi:ss) 我想把日期按小时分类。对于我上面给出的示例,我想创建一个类似于下面列出的值的列表 2017-03-07 0630-07 2017-03-07 07-08 2017-03-07 08-09 2017-03-07 09-10 2017-03-07 10-11 2017-03-07 11-1135 您能推荐一种我可以探

我在程序中收到以下开始日期和结束日期作为输入

2017-03-07 06:30:00至2017-03-07 11:35:00(yyyy-mm-dd hh:mi:ss)

我想把日期按小时分类。对于我上面给出的示例,我想创建一个类似于下面列出的值的列表

2017-03-07 0630-07 
2017-03-07 07-08  
2017-03-07 08-09 
2017-03-07 09-10  
2017-03-07 10-11  
2017-03-07 11-1135

您能推荐一种我可以探索的方法吗?

如果您可以使用Java8,我建议您使用以下方法:

// with LocalDateTime startDate and LocalDateTime endDate defined,
LocalDateTime currentRangeStart = startDate;
while (currentRangeStart.isBefore(endDate)) {
    LocalDateTime nextHour = currentRangeStart.withMinute(0).plusHours(1);
    LocalDateTime currentRangeEnd = nextHour.isBefore(endDate) ? nextHour : endDate;
    System.out.printf("%s - %s%n", currentRangeStart, currentRangeEnd);
    currentRangeStart = currentRangeEnd;
}

你可以在行动中看到它。如果当前有
Date
对象,请检查如何从
Date
转换为
LocalDateTime

我将构建一个从开始日期到计数的映射。类似于

Map<java.util.Date,Integer> map = new TreeMap<>();
Calendar cal = new GregorianCalendar();
for (java.sql.Timestamp exactDate: dates) {
  cal.setTime(exactDate);
  cal.set(Calendar.MINUTE, 0);
  cal.set(Calendar.SECOND, 0);
  cal.set(Calendar.MILLISECOND, 0);
  java.util.Date key = new java.util.Date(cal.getTime());
  Integer count;
  if ((count = map.get(key)) == null) {
    map.put(key, Integer.valueOf(1);
  } else {
    map.put(key, Integer.valueOf(1 + count.intValue()));
  }
}
是好的,但它忽略输入中可能存在的任何秒或秒的分数。此外,我还可以进一步扩展,并应用时区

截断 您可以截断
LocalDateTime
对象,在增加小时数时消除任何整秒或分数秒

LocalDateTime ldtTruncated = ldt.truncatedTo( ChronoUnit.MINUTES ); // Lop off seconds and nanoseconds.
……或者

LocalDateTime ldtTruncated = ldt.truncatedTo( ChronoUnit.HOURS ); // Lop off minutes, seconds, and nanoseconds.
时区 一个关键问题是时区。这些值缺少或的任何指标。正如Aaron所正确显示的,我们应该首先将它们解析为
LocalDateTime

LocalDateTime ldtStart = LocalDateTime.parse ( "2017-03-07 06:30:00".replace ( " " , "T" ) );
LocalDateTime ldtStop = LocalDateTime.parse ( "2017-03-07 11:35:00".replace ( " " , "T" ) );
但从问题的措辞来看,我认为我们希望在特定时刻开展工作。根据定义,
LocalDateTime
不是一个特定的时刻,只是一个潜在时刻的模糊概念。必须添加时区(或偏移)的上下文以确定实际时刻。因此,如果您知道用于这些值的区域,请应用它

ZonedDateTime
类对输入值进行调整,这些输入值对于您的特定时区无效,因为存在异常,例如

确保输入有意义

// Validate the inputs.
if ( zdtStop.isBefore ( zdtStart ) ) {
    // perhaps throw exception
    System.out.println ( "ERROR - stop is befor start." );
    return;
}
日期时间范围作为一对
ZonedDateTime
对象 现在我们可以逐小时递增以生成所需的范围。我们可以使用Three Ten Extra项目(见下文)中的
Interval
类,该类跟踪始终以UTC为单位的一对
Instant
对象。但这对我们来说可能没什么用处,因为我们真的很想使用分区时间(或者我想是这样)。因此,让我们将每个日期时间范围作为一对
ZonedDateTime
类进行跟踪。我们可以为这一对创建我们自己的类,但相反,我们重新定义了类的用途。该类将一对对象作为键和值进行跟踪

不要让配对类的名称迷惑您。该类的最初目的是与
映射一起使用,但其本身不是映射。该类是指一个键和一个来自
映射的值,但我们将使用它的“键”是我们的开始时刻,它的“值”是我们的停止时刻

我们在
AbstractMap.SimpleImmutableEntry
类型的
列表中收集每个计算的时间范围

int initialCapacity = ( ( int ) ChronoUnit.HOURS.between ( zdtStart , zdtStop ) ) + 2; // Plus two for good measure. (not sure if needed).
List<AbstractMap.SimpleImmutableEntry<ZonedDateTime , ZonedDateTime>> ranges = new ArrayList<> ( initialCapacity );
跑步的时候

ldtStart/ldtStop:2017-03-07T06:30/2017-03-07T11:35

zdtStart/zdtStop:2017-03-07T06:30-05:00[美国/蒙特利尔]/2017-03-07T06:30-05:00[美国/蒙特利尔]

范围:[2017-03-07T06:30-05:00[美国/蒙特利尔]=2017-03-07T07:00-05:00[美国/蒙特利尔]、2017-03-07T07:00-05:00[美国/蒙特利尔]=2017-03-07T08:00-05:00[美国/蒙特利尔]=2017-03-07T08:00-05:00[美国/蒙特利尔]、2017-03-07T09:00-05:00[美国/蒙特利尔]、2017-03-03-07T09:00-05:00[美国/蒙特利尔]=2017-03-07T10:00[美国/蒙特利尔],2017-03-07T10:00-05:00[美国/蒙特利尔]=2017-03-07T11:00-05:00[美国/蒙特利尔]=2017-03-07T11:00-05:00[美国/蒙特利尔]=2017-03-07T11:35-05:00[美国/蒙特利尔]]


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

从哪里获得java.time类

  • 后来
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 该项目专门为Android采用了ThreeTen Backport(如上所述)

该项目使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。你可以在这里找到一些有用的课程,如、、和。

对不起,Aaron,我将退出我的帖子,并将清楚地解释它。好的,我现在明白了!我会看看能找到什么。谢谢亚伦,是的,没错。我想按时间跨度对它们进行细分。我还没有把这个编码。我想在实现之前检查一下推荐的方法。你完全可以用Java来做,但通常,当我做这类事情时,这是一次性的工作,我使用类似Python的东西。@PunterVicky标题中提到的地图是从哪里来的?我建议你要么更清楚地解释一下,要么编辑你的标题,删除与你的核心问题不相关的内容。太棒了,亚伦!非常感谢你的帮助。这看起来非常简单和优雅。是的,java 8中引入的
java.time
包确实简化了日期处理:)再次感谢!感谢您的时间和帮助。正是我想要的。谢谢@David!!是的,我也按照你的建议从DB取回。
// Validate the inputs.
if ( zdtStop.isBefore ( zdtStart ) ) {
    // perhaps throw exception
    System.out.println ( "ERROR - stop is befor start." );
    return;
}
int initialCapacity = ( ( int ) ChronoUnit.HOURS.between ( zdtStart , zdtStop ) ) + 2; // Plus two for good measure. (not sure if needed).
List<AbstractMap.SimpleImmutableEntry<ZonedDateTime , ZonedDateTime>> ranges = new ArrayList<> ( initialCapacity );
ZonedDateTime zdt = zdtStart;
while ( zdt.isBefore ( zdtStop ) ) {
    ZonedDateTime zdt2 = zdt.truncatedTo ( ChronoUnit.HOURS ).plusHours ( 1 );  // Truncate to whole hour, and add one.
    if ( zdt2.isAfter ( zdtStop ) ) { // Oops, went too far. Clip this range to end at `zdtStop`.
        zdt2 = zdtStop;
    }
    AbstractMap.SimpleImmutableEntry<ZonedDateTime , ZonedDateTime> range = new AbstractMap.SimpleImmutableEntry<> ( zdt , zdt2 );
    ranges.add ( range );
    // Prepare for next loop.
    zdt = zdt2;
}
System.out.println ( "ldtStart/ldtStop: " + ldtStart + "/" + ldtStop );
System.out.println ( "zdtStart/zdtStop: " + zdtStart + "/" + zdtStart );
System.out.println ( "ranges: " + ranges );