每15分钟Java日期时间比较

我有一个带有时间戳的csv记录,如每隔5分钟:

- 2015/05/19 16:15:00 - 2015/05/19 16:20:00 - 2015/05/19 16:35:00 - 2015/05/19 16:10:00 - 2015/05/19 16:55:00 

我正在使用数组来比较每条记录的日期是否在15分钟内:

 ArrayList per15Min = new ArrayList() {{ add("00,15"); add("15,30"); add("30,45"); add("45,00"); }}; 

我所做的是阅读每条记录,根据“,”将其拆分以提取日期:

 private SimpleDateFormat csvDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); private SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyyMMddHHmm"); // Loop thru each record while ((perLine = br.readLine()) != null) { // Store date per record in a string String[] perColumn = perLine.split(",", -1); String date = perColumn[0]; // Convert record date to yyyyMMddHHmm Date subDateP = csvDateFormat.parse(csvDate); String subDateF = fileDateFormat.format(subDateP); // Extract the date without the day (dd) String subDate = subDateF.substring(0,10); for (int j = 0 ; j = 0) && (csvRd.compareTo(after) < 0)) { System.out.println("DATE HERE" + before + " : " + after + " : " + csvRd); } } } 

正如您在sysout中看到的那样,它似乎不起作用:

 DATE HEREWed May 20 07:30:00 SGT 2015 : Wed May 20 07:45:00 SGT 2015 : Wed May 20 07:30:00 SGT 2015 DATE HEREWed May 20 07:30:00 SGT 2015 : Wed May 20 07:45:00 SGT 2015 : Wed May 20 07:25:00 SGT 2015 DATE HEREWed May 20 07:30:00 SGT 2015 : Wed May 20 07:45:00 SGT 2015 : Wed May 20 07:20:00 SGT 2015 DATE HEREWed May 20 07:30:00 SGT 2015 : Wed May 20 07:45:00 SGT 2015 : Wed May 20 07:15:00 SGT 2015 DATE HEREWed May 20 07:30:00 SGT 2015 : Wed May 20 07:45:00 SGT 2015 : Wed May 20 07:10:00 SGT 2015 

我需要的是,如果时间戳(每5分钟)在15分钟数组内,它将进入条件:

 00-10 minutes must enter at 00,15 15-25 minutes must enter at 15,30 30-40 minutes must enter at 30,45 45-55 minutes must enter at 45,00 

任何人都知道if条件有什么问题吗?

任何时候你需要处理日期/时间信息,你应该使用适当的API,在你的情况下,你可以使用DateCalendar ,但如果你可以使用Java 8的时间API或Joda-Time,因为交互比Calendar更简单

String日期值转换为Date s或(更好) LocalDateTime值并使用它们的比较方法

  • Date#beforeDate#afterDate#equals
  • LocalDateTime#isBeforeLocalDateTime#isAfterLocalDateTime#equals LocalDateTime#isAfter

例如…

 List listOfDateValues = new ArrayList<>(25); listOfDateValues.addAll(Arrays.asList( new String[]{"2015/05/19 16:10:00", "2015/05/19 16:00:00", "2015/05/19 16:05:00", "2015/05/19 16:10:00", "2015/05/19 16:15:00", "2015/05/19 16:20:00", "2015/05/19 16:25:00", "2015/05/19 16:30:00", "2015/05/19 16:35:00", "2015/05/19 16:40:00", "2015/05/19 16:45:00", "2015/05/19 16:50:00", "2015/05/19 16:55:00", "2015/05/19 16:25:00"})); List per15Min = new ArrayList<>( Arrays.asList( new String[]{ "00,15", "16,30", "31,45", "46,59" //?? } ) ); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); Map> mapGroups = new HashMap<>(); for (String dateValue : listOfDateValues) { LocalDateTime ldt = LocalDateTime.parse(dateValue, formatter); for (String range : per15Min) { String[] split = range.split(","); LocalDateTime startRange = ldt.withMinute(Integer.parseInt(split[0])).withSecond(0).withNano(0); LocalDateTime endRange = ldt.withMinute(Integer.parseInt(split[1])).withSecond(59).withNano(999999999); if ((ldt.equals(startRange) || ldt.isAfter(startRange)) && (ldt.equals(endRange) || ldt.isBefore(endRange))) { List group = mapGroups.get(range); if (group == null) { group = new ArrayList(25); mapGroups.put(range, group); } group.add(dateValue); } } } for (String range : per15Min) { List group = mapGroups.get(range); System.out.println(range); for (String dateValue : group) { System.out.println(" -> " + dateValue); } } 

哪个输出……

 00,15 -> 2015/05/19 16:10:00 -> 2015/05/19 16:00:00 -> 2015/05/19 16:05:00 -> 2015/05/19 16:10:00 -> 2015/05/19 16:15:00 16,30 -> 2015/05/19 16:20:00 -> 2015/05/19 16:25:00 -> 2015/05/19 16:30:00 -> 2015/05/19 16:25:00 31,45 -> 2015/05/19 16:35:00 -> 2015/05/19 16:40:00 -> 2015/05/19 16:45:00 46,59 -> 2015/05/19 16:50:00 -> 2015/05/19 16:55:00 

注意,我已经修改了你的游侠,没有任何意义的范围是00-1515-30xx:15.00的时间在哪里? 进入两套?

您提供的代码显示了许多难闻的气味 (或反模式 ):计算机科学家通过经验发现的模式会导致很多问题。

最有问题的是你依赖字符串格式化和解析。

仅对文本使用字符串,而不是像元组日期等所有类型数据的某些中间表示

特别是对于像Date这样的文化依赖概念,这可能导致完全混乱。 例如,某些文化可能不会使用阿拉伯数字(如12 )编写日期,但例如使用罗马数字(如XII )。 或者在某个时间点,年份将不再具有四位数的可表示,或者一个用时区12:15:57 UTC+01解析日期,但在格式化和解析期间时区丢失。 一般来说, 使用字符串处理进行数据处理是一个坏主意 ,只有在数据为text / names / strings /时才这样做。

接下来你似乎存储了15倍数,这有点无用。 它会减慢这个过程。

不要明确存储倍数等,只使用powershell方法 (如果绝对必要,可以枚举元素)。

在这个答案中,我提出了两种方法: dateFloor(Date d, int m)dateCeil(Date d, int m) 。 您可以传递分钟数 – 在本例中为15作为额外参数来设置粒度。

 public static Date dateFloor (Date d, int m) { Date d2 = (Date) d.clone(); d2.setMinutes((d2.getMinutes()/m)*m); return d2; } public static Date dateCeil (Date d, int m) { Date d2 = (Date) d.clone(); d2.setMinutes(((d2.getMinutes()+m)/m)*m); //alternatively: d2.setMinutes((d2.getMinutes()/m)*m+m); return d2; } 

DateFloor可以计算出日期,并模拟DateCeil计算的日期。

使用这些方法,方法很简单:

 Scanner sc = new Scanner(System.in); while(sc.hasNext()) { String line = sc.nextLine(); Date date = csvDateFormat.parse(line); Date before = dateFloor(date,15); Date after = dateCeil(date,15); System.out.print(before); System.out.print(" <= "); System.out.print(date); System.out.print(" < "); System.out.println(after); } 

只有两行用于实现业务逻辑 ......

您可以在此处找到在线Ideone演示 。

我没有进行csv解析,所以你仍然必须在逗号上拆分并提取第一部分。 但这不是至关重要的部分。

对于您的给定输入 - 没有破折号( - ) - 它提供以下输出:

 Tue May 19 16:15:00 GMT 2015 <= Tue May 19 16:15:00 GMT 2015 < Tue May 19 16:30:00 GMT 2015 Tue May 19 16:15:00 GMT 2015 <= Tue May 19 16:20:00 GMT 2015 < Tue May 19 16:30:00 GMT 2015 Tue May 19 16:30:00 GMT 2015 <= Tue May 19 16:35:00 GMT 2015 < Tue May 19 16:45:00 GMT 2015 Tue May 19 16:00:00 GMT 2015 <= Tue May 19 16:10:00 GMT 2015 < Tue May 19 16:15:00 GMT 2015 Tue May 19 16:45:00 GMT 2015 <= Tue May 19 16:55:00 GMT 2015 < Tue May 19 17:00:00 GMT 2015 

其他错误

您所做的一个概念性错误是,当您将日期格式化为字符串,并且您尝试生成最后15分钟的部分时,它会向其追加00 ,从而导致时间低于实际时间 ,因为您的方法不是先增加小时数。

其他建议

您将I / O与计算某些内容的方法混合在一起。 控制器模式表明您必须分解这些问题。 此外,您最好使用csv解析器。 如果你在.csv文件中使用像"foo,bar",baz这样的字符串,你将在foobar之间进行分割。 这不符合标准。

我收到的答案都很棒,但是我要部署的服务器只有1.5版的java版本,所以我不会使用很多API库,因为有些不兼容。

基本上我找到了一个解决方案:

 while ((perLine = br.readLine()) != null) { // Split row per column String[] perColumn = perLine.split(",", -1); // Convert unix date to yyyyMMddHHmm java.util.Date time = new java.util.Date(Long.parseLong(perColumn[0]) * 1000); String csvDateNoDay = fileDateFormat.format(time).substring(0,10); long csvDateYsDay = fileDateFormat.parse(fileDateFormat.format(time)).getTime(); // Date of the file to be created/used String fileDate = ""; String fileUnixDate = ""; for (int j = 0 ; j < per15Min.size() ; j++) { String[] s = per15Min.get(j).split(",", -1); long isBeforeDate = fileDateFormat.parse(csvDateNoDay + s[0]).getTime(); long isAfterDate = fileDateFormat.parse(csvDateNoDay + s[1]).getTime(); /* Compare the Date for each record versus the list of array: * Record (Minutes) Array Filename Date * 00 - 14 00 yyyyMMddHH00 * 15 - 29 15 yyyyMMddHH15 * 30 - 44 30 yyyyMMddHH30 * 45 - 59 45 yyyyMMddHH45 */ if ((csvDateYsDay>isBeforeDate && csvDateYsDay 

fileDate和fileDateUnix字符串将具有正确的日期,该日期将用于命名新的csv文件并根据每15分钟的时间戳拆分每个recod。