Java datetime比较每15分钟 [英] Java datetime comparison per 15 minutes

查看:123
本文介绍了Java datetime比较每15分钟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

   -  2015/05/19 16:15:我有一个csv记录, 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< String> per15Min = new ArrayList< String>(){{
add(00,15);
add(15,30);
add(30,45);
add(45,00);
}};

我所做的是读取每个记录,根据,分解它来提取日期: / p>

  private SimpleDateFormat csvDateFormat = new SimpleDateFormat(yyyy / MM / dd HH:mm:ss); 
private SimpleDateFormat fileDateFormat = new SimpleDateFormat(yyyyMMddHHmm);

//循环通过每个记录
while((perLine = br.readLine())!= null){

//存储每个记录的日期string
String [] perColumn = perLine.split(,,-1);
String date = perColumn [0];

//将记录日期转换为yyyyMMddHHmm
日期subDateP = csvDateFormat.parse(csvDate);
String subDateF = fileDateFormat.format(subDateP);

//解压缩日期(dd)
String subDate = subDateF.substring(0,10);

for(int j = 0; j String [] s = per15Min.get(j).split(,, - 1);
String m1 = s [0];
String m2 = s [1];

//所有日期都是yyyyMMddHHmm格式
Date before = fileDateFormat.parse(subDate + m1);
Date after = fileDateFormat.parse(subDate + m2);
日期csvRd = fileDateFormat.parse(date);

System.out.println(DATE+ before +:+ after +:+ csvRd);

//做日期比较有问题
if((before.compareTo(csvRd)> = 0)&&(csvRd.compareTo(after)< 0)){
System.out.println(DATE HERE+ before +:+ after +:+ csvRd);
}


}
}

正如你可以从sysout看到的似乎不起作用:

  DATE HEREDED 5月20日07:30: 00 SGT 2015:Wed May 20 07:45:00 SGT 2015:Wed May 20 07:30:00 SGT 2015 
DATE HEREDED 5月20日07:30:00 SGT 2015:Wed May 20 07:45:00 SGT 2015:Wed May 20 07:25:00 SGT 2015
DATE HEREDED 5月20日07:30:00 SGT 2015:Wed May 20 07:45:00 SGT 2015:Wed May 20 07:20:00 SGT 2015
DATE HEREDED 5月20日07:30:00 SGT 2015:Wed May 20 07:45:00 SGT 2015:Wed May 20 07:15:00 SGT 2015
DATE HEREDED 5月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分钟必须输入00,15 
15-25分钟必须输入15,30
30-40分钟必须输入30,45
45-55分钟必须输入45,00

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

解决方案

您提供的代码显示了很多不良气味(或反模式) :计算机科学家通过经验发现造成很多问题的模式。



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


只能使用文本的字符串,而不是像这样的各种数据的某些中间表示元组日期等等


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



时才执行此操作

接下来,您似乎存储了 15 的倍数,这是有点无用的。这将减慢进程。


不要显式存储倍数等,只能使用强力方法>(如果绝对必要的话,你可以列举元素。


在这个答案中,我提出两种方法: dateFloor (日期d,int m) dateCeil(Date d,int m)可以传递分钟数 - 在这种情况下 15 作为设置粒度的额外参数。

  public static Date dateFloor日期d,int m){
日期d2 =(日期)d.clone();
d2.setMinutes((d2.getMinutes()/ m)* m);
返回d2 ;
}

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

DateFloor 可以先计算 日期并模拟 DateCeil 计算日期后的



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

 扫描仪sc =新扫描仪。在); 
while(sc.hasNext()){
String line = sc.nextLine();
日期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(之后);
}

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



您可以在线查找 Ideone 演示这里



我没有做 csv 解析,所以你还必须分开逗号并提取第一部分。但是这不是重要的部分。



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

 星期二5月19日16:15:00 GMT 2015< = Tue May 19 16:15:00 GMT 2015 <星期二5月19日16:30:00 GMT 2015 
星期二5月19日16:15:00 GMT 2015< = 5月19日16:20:00 GMT 2015< 5月19日星期二16:30:00 GMT 2015
星期二5月19日16:30:00 GMT 2015< = 5月19日16:35:00 GMT 2015<星期二5月19日16:45:00 GMT 2015
星期二5月19日16:00:00 GMT 2015年5月19日16:10:00 GMT 2015<周五5月19日16:15:00 GMT 2015
星期二5月19日16:45:00 GMT 2015< = 5月19日16:55:00 GMT 2015星期二5月19日17:00:00 GMT 2015



其他错误



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



其他建议



您可以将I / O与计算某些东西的方法进行混合。 控制器模式表示您必须拆分这些问题。此外,您最好使用csv解析器。如果您在 .csv 文件中使用foo,bar,baz 之类的字符串,则您将在 foo bar 。这不符合标准。


I have a csv records with timestamps like or every 5 minutes:

- 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

I'm using an array to compare if the dates per record is within 15 minutes:

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

What I do is read each record, split it based on "," to extract the Dates:

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 < per15Min.size() ; j++) {
        String[] s = per15Min.get(j).split(",", -1);
        String m1 = s[0];
        String m2 = s[1];

        // All dates are in a yyyyMMddHHmm format
        Date before = fileDateFormat.parse(subDate + m1);
        Date after = fileDateFormat.parse(subDate + m2);
        Date csvRd = fileDateFormat.parse(date);

        System.out.println("DATE " + before + " : " + after + " : " + csvRd);

        // Having problems doing date comparison            
        if ((before.compareTo(csvRd) >= 0) && (csvRd.compareTo(after) < 0)) {
            System.out.println("DATE HERE" + before + " : " + after + " : " + csvRd);
        }


    }
}

As you can see based from the sysout it doesn't seem to work:

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

What I need is something like if the timestamp (per 5 min) is within the 15 minute array it will enter the condition:

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

Anyone knows whats wrong with the if condition?

解决方案

The code you provide, shows a lot of bad smells (or anti-patterns): patterns computer scientists have found out through experience that cause a lot of problems.

The most problematic is that you rely on string formatting and parsing.

Only use strings for text, not as some intermediate representation of all kinds of data like tuples, Date's, etc.

Especially for culture dependent concepts like Date's this can result in total chaos. For instance it is possible that some culture doesn't write dates using Arabic numbers (like 12), but for instance uses Roman numbers (like XII). Or perhaps at some point in time the year will not be representable anymore with four digits, or one parses the date with timezone 12:15:57 UTC+01, but the timezone is lost during formatting and parsing. In general it is a bad idea to do data processing using string processing, only do this if the data is text/names/strings/...

Next you seem to store multiples of 15, which is a bit unusefull. It will slow down the process.

Don't store multiples, etc. explicitly and only use brute force approaches (where you enumerate over the elements if absolutely necessary.

In this answer I propose two methods: dateFloor(Date d, int m) and dateCeil(Date d, int m). You can pass the number of minutes - in this case 15 as an extra parameter to set the granularity.

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;
}

The DateFloor can calculate the before date and analogue the DateCeil calculate the after date.

Using these methods, the method is as simple as:

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);
 }

Only two lines are used to implement the business logic...

You can find an online Ideone demo here.

I didn't do the csv parsing, so you still have to split on the comma and extract the first part. But that's not the vital part.

For your given input - without the dashes (-) - it gives the following output:

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

Other errors

A conceptual error you've made is that when you format the date as a string, and you try to generate the last 15 minutes part, it will append 00 to it resulting in a time lower than the actual time, because your method does not increment the hours first.

Additional advice

You mix I/O with methods that calculate something. The controller pattern says you must split these concerns. Furthermore you better use a csv parser. If you use strings like "foo,bar",baz in a .csv file, you will split between foo and bar. That's not according to the standards.

这篇关于Java datetime比较每15分钟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆