【问题标题】:comparing time between two files which are part of the file name比较作为文件名一部分的两个文件之间的时间
【发布时间】:2019-07-07 04:51:39
【问题描述】:

我有 2 个文件的时间戳不同

command_step_output/2019/02/13/ea768d46-85bb-4833-8326-fb6be6d60a89_20190213_105228_command_step_output.csv.gz

command_step_output/2019/02/13/ea768d46-85bb-4833-8326-fb6be6d60a89_20190213_105325_command_step_output.csv.gz

它们之间的唯一区别是文件名结束之前的时间是不同的 105228(表示 10:52:28)和 105325(表示 10:53:25),我希望能够比较它们并在这个例子中使用这个逻辑给它一个少 1 分钟或多 1 分钟的缓冲区,文件的名称是相同的,我希望能够使用这个缓冲区来比较它们,我尝试了一些方法,但它没有给我解决方案。

【问题讨论】:

  • 您只想比较名称并检查名称中插入的日期时间是否相差小于 1 分钟?
  • @DavideLorenzoMARINO - 是的
  • 另外我有很多文件都是这样的,所以我遍历了 2 个列表,这些列表得到了具有这种模式的文件名,我想比较它们有可能文件名可能不是来自同一日期格式(20090213 与 20090211),它们当然不相同。
  • 你试过什么?你被困在哪里?读取文件名?提取日期?比较日期?
  • 比较日期本身这部分:20190213_105325

标签: java string list file date


【解决方案1】:

java.time

计算两条路径的时间差:

    String onePath     = "command_step_output/2019/02/13/ea768d46-85bb-4833-8326-fb6be6d60a89_20190213_105228_command_step_output.csv.gz";
    String anotherPath = "command_step_output/2019/02/13/ea768d46-85bb-4833-8326-fb6be6d60a89_20190213_105325_command_step_output.csv.gz";

    LocalDateTime oneTime = extractDateTime(onePath);
    LocalDateTime anboherTime = extractDateTime(anotherPath);

    Duration diff = Duration.between(oneTime, anboherTime);
    diff = diff.abs();

在最后一行中对abs 的调用将任何负差转换为正差,确保缓冲区少1 分钟和多1 分钟。 extractDateTime 在这个答案的底部。要知道差异是否小于一分钟,有不同的方法,我想向您展示几个选项。先说简单的:

    if (diff.toMinutes() < 1) {
        System.out.println("Within the window: " + diff);
    }

窗口内:PT57S

我已经打印了消息中的差异,看起来有点搞笑。格式为 ISO 8601。读作“一段 57 秒的时间”。

上面的缺点是它只能工作整分钟。如果有一天您想将缓冲区更改为 45 秒或 1 分 30 秒怎么办?以下是更笼统的:

    Duration buffer = Duration.ofMinutes(1);
    if (diff.compareTo(buffer) < 0) {
        System.out.println("Within the window: " + diff);
    }

我本来希望 Duration 有一个 isShorterThan 方法,但它没有。如果您发现使用 compareTo 的代码难以阅读,那么您并不孤单。另一种方法是减去,看看结果是否为负:

    if (diff.minus(buffer).isNegative()) {
        System.out.println("Within the window: " + diff);
    }

我答应你辅助方法的代码:

private static LocalDateTime extractDateTime(String path) {
    String dateTimeString = path.replaceFirst("^.*/[0-9a-f-]+_(\\d+_\\d+)_command_step_output\\.csv\\.gz$", "$1");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMdd_HHmmss"); 
    return LocalDateTime.parse(dateTimeString, formatter);
}

我正在使用replaceFirst 和正则表达式来提取20190213_105228 部分。然后将其解析为LocalDateTime 对象。

链接

【讨论】:

  • 感谢您的详细回答,非常感谢。我在其他文件名约定上尝试了您的代码,但出现以下错误: Text 'alert/2019/02/14/5c7e6daa-5139-4a70-ac5c-c36f49163e05_20190214_1...' could not be parsed at index 0 when I used ' extractDateTime'函数在这一行:return LocalDateTime.parse(dateTimeString, formatter);
  • 好吧,那么另一个文件名与我用于从文件名中提取日期和时间部分的正则表达式不匹配(例如,它可能不以command_step_output.csv.gz 结尾? ) 如果是这样,您需要以某种方式放松正则表达式。
  • 也许使用'.'作为正则表达式匹配任何字符?
  • 我用 .+ 解决了问题,而不是文件名
【解决方案2】:

首先提取日期:

private Date extractDate(String filename) {
  // Updated to extract the date not from filename, but file and path name
  int startDate = filename.indexof('_', filename.lastIndexof('/'));
  int endDate = startDate + 15;
  String dateStr = filename.substring(start, end);

  // Use a date format for the part of string representing the dates
  SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss");
  return format.parse(dateStr);
}

然后编写一个函数来检查提取的日期是否在不到 1 分钟的距离内。

public boolean samePeriod(String filename1, String filename2) {
  Date date1 = extractDate(filename1);
  Date date2 = extractDate(filename2);
  long msDistance = Math.abs(date1.getTime() - date2.getTime());

  // 1 minute is 1000 * 60 milliseconds
  return msDistance <= 1000 * 60;
}

请注意,您必须通过检查空值和处理异常来丰富此答案。这只是开发代码的基础。

【讨论】:

  • 在您的 extractDate 函数中,您使用的是 string.indexOf('') 在这种情况下,它不会为您提供文件名开头的索引 ' ' 在命令之后?
  • 请不要教年轻人使用早已过时且臭名昭著的SimpleDateFormat类。至少不是第一选择。而且不是没有任何保留。今天我们在java.time, the modern Java date and time API 和它的DateTimeFormatter 中做得更好。
  • 文件名是ea768d46-85bb-4833-8326-fb6be6d60a89_20190213_105228_command_step_output.csv.gz,其他部分是目录名的全路径
  • @DavideLorenzoMARINO - 完整路径是来自 S3 的文件名的一部分,所以我也需要比较路径。
  • @tupacshakur 我用你的信息更新了答案。请注意,该函数仅检查日期的距离,因此如果它们位于不同的目录但名称更接近,则该函数返回 true。
【解决方案3】:

如果您希望每个文件名都有通用比较器,请检查此

public static void compareStringsByChar(String in1,String in2) {
    //assuming same strings
    if(in1.length() == in2.length()) {
        //collector of diffs
        StringBuilder sbDiff = new StringBuilder();
        //just for log bellow
        int firstDiffIndex = -1;
        //if diff is not in sequence, then will be used for putting comma in collected data
        int lastDiffIndex = -1;

        for (int i = 0; i < in1.length(); i++) {
            //diff found
            if(in2.charAt(i) != in1.charAt(i)) {
                //first diff found
                if(sbDiff.length() ==0 ) {
                    firstDiffIndex = i;
                }

                //checking if in sequence
                if(lastDiffIndex != -1 && lastDiffIndex != (i-1)) {
                    sbDiff.append(",");
                }
                //finally add char diff and change reference to the last occurence
                sbDiff.append(in2.charAt(i));
                lastDiffIndex = i;
            }
        }

        if(!sbDiff.toString().isEmpty()) {
            System.out.println("Found difference at pos." + firstDiffIndex);
            System.out.println("String1: " + in1.substring(firstDiffIndex));
            System.out.println("String2: " + in2.substring(firstDiffIndex));
            System.out.println("Diffs strings: " + sbDiff.toString());
        }
    }
}

对于您的数据:

String st1 = "command_step_output/2019/02/13/ea768d46-85bb-4833-8326-fb6be6d60a89_20190213_105228_command_step_output.csv.gz";
        String st2 = "command_step_output/2019/02/13/ea768d46-85bb-4833-8326-fb6be6d60a89_20190213_105325_command_step_output.csv.gz";

输出:

Found difference at pos.80
String1: 228_command_step_output.csv.gz
String2: 325_command_step_output.csv.gz
Diffs strings: 3,5

#in case of diff sequence:
Found difference at pos.80
String1: 228_command_step_output.csv.gz
String2: 345_command_step_output.csv.gz
Diffs strings: 345

【讨论】:

  • 感谢您的详细回答,但在我的示例中,我不关心时间戳的差异文件是相同的,因为我可以“吸收”时间戳中一分钟的差异:20190213_105228 和 20190213_105325 在我的情况是因为时间不到一分钟。
  • 请考虑,如果这两个名称仅相差一秒,但它们的日期不同,则您的代码将不起作用(例如 *20180202_000000 和 *20180201_235959)
猜你喜欢
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 2011-06-08
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
相关资源
最近更新 更多