【问题标题】:Adding time doesn't add up添加时间不会累加
【发布时间】:2018-04-23 08:30:52
【问题描述】:

对不起,我来找你的问题应该已经回答了。唉,我的 google-foo 很弱,我谦卑地来请求您的指导。

为什么会出现额外的 59 分钟??

好的,所以我有一个“打卡”的事情,当人们外出的分钟数与分钟数相同时,我的计算就会出错。我记得以前听说过这个问题,但没有解决方案。只是一个“嗯,就是这样。祝你好运,布拉。”我已经尝试在计算过程中添加和减去分钟,但这只会推动问题+/-添加/减去的时间。我也试过计算到第二个(下面没有显示),但这也没有帮助。

必须的,这是我的代码:

//calculateTotalHours() 
public static String calculateTotalHours(Cell inTime, Cell outTime, Cell breakStart, Cell breakEnd)
{
    System.out.println(LOG + "calculateTotalHours");
    SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
    Date in, out, start, end;       
    
    if(null != inTime && null != outTime && null != breakStart && null != breakEnd)
    {   
        try
        {
            in = timeFormat.parse(inTime.getStringCellValue());
            out = timeFormat.parse(outTime.getStringCellValue());
            start = timeFormat.parse(breakStart.getStringCellValue());
            end = timeFormat.parse(breakEnd.getStringCellValue());

            long lunchTotal = end.getTime() - start.getTime();
            long totalWork = out.getTime() - in.getTime();
            long totalTime = totalWork - lunchTotal;            
            long diffHours = totalTime/HOURS % 24;
            totalTime -= diffHours;
            long diffMinutes = totalTime/MINUTES % 60;
            totalTime -= diffMinutes;       
            
            return String.format("%02d:%02d", diffHours, diffMinutes);
        } 
        catch (ParseException e) {e.printStackTrace();}
    }
    else
    {
        try
        {
            if(null == breakStart || null == breakEnd)              {
                in = timeFormat.parse(inTime.getStringCellValue());
                out = timeFormat.parse(outTime.getStringCellValue());           
                
                long totalTime = out.getTime() - in.getTime();              
                long diffHours = totalTime/HOURS % 24;
                totalTime -= diffHours;
                long diffMinutes = totalTime/MINUTES % 60;
                totalTime -= diffMinutes;
                
                return String.format("%02d:%02d", diffHours, diffMinutes);
            }
            else if(null == inTime.getStringCellValue())
            {
                System.out.println(LOG + "inTime is blank");
                return "-1";
            }
        } 
        catch (ParseException e) {e.printStackTrace();}
    }
    return "-1";
}   

我对我的代码造成的混乱表示诚挚的歉意。让我知道是否按秒或毫秒计算是要走的路。我在尝试这种方式时可能忽略了一些东西。

2020 年更新:

我想更新我的代码以及我应该做的事情。首先,我应该更多地分离单元格、字符串和时间。其次,为了清楚起见,我应该将其分解为更多方法。

我将只显示 getTotalHours(startTimeString, endTimeString):

    DateTimeFormatter format = DateTimeFormatter.ofPattern("HH:mm");
    LocalTime end = LocalTime.parse(endTimeString.trim(), format);
    LocalTime start = LocalTime.parse(startTimeString.trim(), format);
    
    return   Duration.between(start, end).toHoursPart()%24 
           + ":"
           + Duration.between(start, end).toMinutes()%60;

【问题讨论】:

  • 为什么不使用LocalTimeLocalDateTime
  • 处理时间和日期的第一课:在任何情况下都不要自己计算。您会假设某些不正确的事情,例如所有分钟都有 60 秒。
  • 避开SimpleDateFormat 和它的朋友们,这很麻烦,而且他们早就过时了。使用来自java.time(现代Java 日期和时间API)的Duration 来处理时间量。
  • 你的常量HOURSMINUTES,它们是怎么定义的?并不是说您应该自己声明这些常量,只是想了解更确切的问题所在。
  • @SeverityOne 我怎么能不假设所有分钟都有 60 秒?但是,是的,我尝试让我的 excel 表为我计算,但我在某处读到最好以编程方式完成。我知道我遗漏了一些东西:int SECONDS = 1000; int MINUTES = 60*SECONDS;整数小时 = 60*分钟;一旦我掌握了 LocalTime API,我将避免使用这些 API。

标签: java date time simpledateformat


【解决方案1】:

在处理getTime() 返回的时间值以毫秒为单位这一事实时,您的数学完全错误。

我猜(因为上面没有显示)HOURSMINUTES 分别是一小时和一分钟毫秒数的常量?如果是这样,您只是部分处理了单位为毫秒的事实,因为当您这样做时:

totalTime -= diffHours;

...你只会从你的总时间中减去几毫秒,没有达到我认为你认为你正在完成的事情,这就是删除所有的时间,剩下的就是几分钟。

这段代码还有其他问题,但这是最明显的问题。

【讨论】:

  • 这是一个巨大的疏忽。对于那个很抱歉。我以为我正确地遵循了一个示例,但再次检查它,我发现它哪里出错了。下面是另一个代码。 @OleV.V 展示了如何使用 LocalTime 而不是 SimpleDateFormat 的示例。另一位用户还建议切换到该 API 和 LocalDateTime。我会这样做,直到我想再次把头撞到墙上。谢谢!
【解决方案2】:
private static final String defaultHours = "-1";

public static String calculateTotalHours(Cell inTime, Cell outTime, Cell breakStart, Cell breakEnd)
{
    try {
        LocalTime inLocalTime = LocalTime.parse(inTime.getStringCellValue());
        LocalTime outLocalTime = LocalTime.parse(outTime.getStringCellValue());
        LocalTime breakStartTime = LocalTime.parse(breakStart.getStringCellValue());
        LocalTime breakEndTime = LocalTime.parse(breakEnd.getStringCellValue());

        Duration lunch = Duration.between(breakStartTime, breakEndTime);
        Duration present = Duration.between(inLocalTime, outLocalTime);
        Duration worked = present.minus(lunch);

        return String.format("%02d:%02d", worked.toHours(), worked.toMinutesPart());

    } catch (DateTimeParseException dtpe) {
        System.out.println(dtpe);
        return defaultHours;
    }
}

上面的代码使用了toMinutesPart在Java 9的Duration中引入的方法。假设你使用的是ThreeTenABP(详情如下)或更早的Java版本,它是:

        long hours = worked.toHours();
        long minutes = worked.minusHours(hours).toMinutes();
        return String.format("%02d:%02d", hours, minutes);

为了清楚起见,我省略了空检查,我相信你可以处理这些。

正如 cmets 中所说,将时间数学留给经过良好测试的库方法。它不仅不易出错,而且代码更清晰。我正在使用现代 Java 日期和时间 API java.time。它还使我们免于指定显式格式化程序,因为 LocalTime.parse() 将您的 HH:mm 格式解析为默认格式(它是 ISO 8601 格式)。

你的代码出了什么问题?

作为the other answer 中的kshetline,我相信totalTime 以毫秒为单位,diffHours 以小时为单位。因此,当您执行totalTime -= diffHours; 时,您会从毫秒中减去小时数,您一定会得到不正确的结果(顺便说一下,totalTime -= diffMinutes; 也一样,但是您没有使用后一个减法的结果,所以这个错误不显示)。

问题:我可以在 Android 上使用 java.time 吗?

是的,java.time 在较旧和较新的 Android 设备上运行良好。它只需要至少 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备上(据我所知,从 API 级别 26 开始)现代 API 是内置的。
  • 在 Java 6 和 7 中,获取 ThreeTen Backport,即新类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从 org.threeten.bp 导入日期和时间类以及子包。

链接

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-30
    • 2023-01-29
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    相关资源
    最近更新 更多