Java的总时数和分钟数

问题描述

将小时和分钟相加会导致错误的答案。

这里有2个带有小时的列表。

[[0小时:0分钟:0秒,1小时:16分钟:22秒,0小时:1分钟:53秒,23小时:54分钟:18秒],[0小时:8分钟:22秒,0小时:8分钟:22秒,0小时:8分钟:22秒]]这是小时

然后,我将其划分为子列表,以针对每个列表进行计算。这是子列表之一。

[0小时:0分钟:0秒,1小时:16分钟:22秒,0小时:1分钟:53秒,23小时:54分钟:18秒]

因此,我为此子列表获得的答案是:1小时:12分钟:33秒,这是不正确的。我想大约要花25个小时再加上几分钟。

public List<String> getTheHoursWorked() {
    DateTimeFormatter parser = DateTimeFormatter.ofPattern("H 'hours :' m 'mins :' s 'sec'",Locale.US);
    final DateFormat dt = new SimpleDateFormat("HH:mm:ss");
    final Calendar c = Calendar.getInstance(TimeZone.getDefault(),Locale.getDefault());

    c.clear();
    long startingMS = c.getTimeInMillis();
    int counter = 0;

    for (int k = 0; k < hours.size(); k++){
        List<Object> shorter = new ArrayList<>();
        List<Object> temp;
        temp = (List<Object>) hours.get(k);
        
        long milliseconds = 0;
        for (int m = 0; m < shorter.size(); m++) {
            LocalTime odt = LocalTime.parse((CharSequence) shorter.get(m),parser);
            DateTimeFormatter formatter =
                    DateTimeFormatter.ofPattern("HH:mm:ss");
            String printDate = formatter.format(odt);
            try {
                milliseconds = milliseconds + (dt.parse(printDate).getTime() - startingMS);
                System.out.println(milliseconds + "MILISECONDS");
            } catch (ParseException e) {
                e.printstacktrace();
            }
        }
        hoursToString.add(String.valueOf(shorter));
        String s = milliseconds / 1000 % 60   + " seconds";
        String m = milliseconds /(60 * 1000) % 60 + " minutes";
        String h = milliseconds / (60 * 60 * 1000) % 24 + " hours";
        String together = h+":"+m+":"+s;
        togetherHours.add(together);
    }
    return togetherHours;
}

解决方法

解决方案的步骤应该是

  1. 以时间0:0
  2. 开始
  3. 对列表进行迭代,并使用相应的格式程序解析时间字符串后分别添加所有小时,分钟和秒。
  4. 如果分钟和/或秒超过60,则调整小时,分钟和秒。

演示:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = List.of("0 hours : 0 mins : 0 sec","1 hours : 16 mins : 22 sec","0 hours : 1 mins : 53 sec","23 hours : 54 mins : 18 sec");

        // Start with a time of 0:0
        int sumHours = 0;
        int sumMinutes = 0;
        int sumSeconds = 0;

        // Iterate the list and add all hours,minutes and seconds separately after
        // parsing the time strings using the corresponding formatter
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("H' hours : 'm' mins : 's' sec'");
        for (String strTime : list) {
            LocalTime time = LocalTime.parse(strTime,timeFormatter);
            sumHours += time.getHour();
            sumMinutes += time.getMinute();
            sumSeconds += time.getSecond();
        }

        // Adjust hour,minutes and seconds if minute and/or second exceed 60
        sumMinutes += sumSeconds / 60;
        sumSeconds %= 60;
        sumHours += sumMinutes / 60;
        sumMinutes %= 60;

        String strSum = String.format("%d hours : %d mins : %d sec",sumHours,sumMinutes,sumSeconds);
        System.out.println(strSum);
    }
}

输出:

25 hours : 12 mins : 33 sec
,

一种解决方法是使用Duration。将每个时间值转换为持续时间,然后求和。提供的时间值以两个字符串的数组形式显示。

String[] hours = {
        "0 hours : 0 mins : 0 sec,1 hours : 16 mins : 22 sec,0 hours : 1 mins : 53"
                + "sec,23 hours : 54 mins : 18 sec","0 hours : 8 mins : 22 sec,0 hours : 8"
                + " mins : 22 sec,0 hours : 8 mins : 22 sec" };

使用流完成转换。评论中说明了该过程。

List<Duration> times = Arrays.stream(hours)
        // remove all the spaces in each string
        .map(str -> str.replaceAll("\\s+",""))

        // split each string on the commas.  At this
        // point,each string is processed independently
        // of the other in a separate stream
        .map(str -> Arrays.stream(str.split(","))
                
                // parse the time
                .map(tm -> LocalTime.parse(tm,DateTimeFormatter.ofPattern(
                                "H'hours':m'mins':s'sec'")))

                // convert each time to a duration
                .map(lt -> Duration
                        .between(LocalTime.of(0,0),lt))

                // sum the durations
                .reduce(Duration.ZERO,(a,b) -> a.plus(b)))
        // and collect in a list
        .collect(Collectors.toList());

此时,您可以使用标准的“持续时间”格式打印持续时间。

times.forEach(System.out::println);

打印

PT25H12M33S
PT25M6S

要以更熟悉的格式打印它们,可以使用以下lambda。

Function<Duration,String> durationToString = d -> {
    StringBuilder timeString = new StringBuilder();   
    long h = d.toDaysPart()*24+d.toHoursPart();
    timeString.append(h == 1 ? (h + " hour ") : h > 1 ?  (h + " hours ") : "");
    long m = d.toMinutesPart();
    timeString.append(m == 1 ? (m + " minute ") : m > 1 ? (m + " minutes ") : "");
    long s = d.toSecondsPart();
    timeString.append(s == 1 ? (s + " second ") : s > 1 ? (s + " seconds ") : "");
    return timeString.toString();
};

打印

25 hours 12 minutes 33 seconds 
25 minutes 6 seconds 
,
  1. 您的例程中的逻辑错误为%24,因此您将删除整整一天。

  2. 您的代码包含许多无用的部分,例如temp,而且不干净。

  3. 在循环中构建解析器是非常糟糕的样式。

  4. 您执行了很多不必要的工作,并且使用毫秒和日历是没有用的。这是两个返回预期结果的版本。第二个是更新的Java版本。

     public static List<String> getTheHoursWorked() {
     final DateTimeFormatter parser = DateTimeFormatter.ofPattern("H 'hours :' m 'mins :' s 'sec'",Locale.US);
     final List<String> togetherHours = new LinkedList<>();
     for (int k = 0; k < hours.size(); k++){
         final List<String> shorter = hours.get(k);
         long seconds = 0;
         for (int m = 0; m < shorter.size(); m++) {
             final LocalTime odt = LocalTime.parse(shorter.get(m),parser);
             seconds += odt.getHour() * 3600 + odt.getMinute() * 60 + odt.getSecond();
         }
         final String s = (seconds       ) % 60 + " seconds";
         final String m = (seconds /   60) % 60 + " minutes";
         final String h = (seconds / 3600)      + " hours";
         final String together = h+":"+m+":"+s;
         togetherHours.add(together);
     }
     return togetherHours;
     }
    
     public static List<String> getTheHoursWorked_new() {
     final DateTimeFormatter parser = DateTimeFormatter.ofPattern("H 'hours :' m 'mins :' s 'sec'",Locale.US);
     final List<String> togetherHours = new LinkedList<>();
     for (final var shorter: hours){
         long seconds = 0;
         for (final var duration : shorter) {
             final LocalTime odt = LocalTime.parse(duration,parser);
             seconds += odt.getHour() * 3600 + odt.getMinute() * 60 + odt.getSecond();
         }
         final String s = (seconds       ) % 60 + " seconds";
         final String m = (seconds /   60) % 60 + " minutes";
         final String h = (seconds / 3600)      + " hours";
         final String together = h+":"+m+":"+s;
         togetherHours.add(together);
     }
     return togetherHours;
     }