在 Java 中减去两次

Subtracting Two Times in Java

之前我问过一个关于减去时间的问题,我以为我知道了。然而,当我调试时,出现了几个错误。基本上我要问的是创建一个打卡时钟,但我不能使用 Java 日历 API.

用户将输入开始时间和他们打卡的时间,它会计算时间之间的差异。

我的不太好用,我也不知道为什么。例如,如果 4:00am 是开始,12:00am 是结束,则返回 8 小时 00 分钟。那是不正确的。我以为我为可能性创建了一个 if 语句。

这是我的代码:

     public static void elapsedTime()
    {
        Scanner reader = new Scanner (System.in);

        System.out.print("Enter the beginning hour: ");
        int startingHour = reader.nextInt();

        System.out.print("Enter the beginning minute(s): ");
        int startingMin = reader.nextInt();


        System.out.print("Enter AM/PM: ");
        reader.nextLine();
        String startingTOD = reader.nextLine();


        System.out.print("Enter the ending hour: ");
        int endingHour = reader.nextInt();

        System.out.print("Enter the ending minute(s): ");
        int endingMin = reader.nextInt();

        System.out.print("Enter AM/PM:  ");
        reader.nextLine();
        String endingTOD = reader.nextLine();

        System.out.println();

        int hours;
        int minutes = endingMin - startingMin;
        String Am = "am" ;
        String Pm = "pm" ;

       if (endingTOD.equalsIgnoreCase(startingTOD) &&  minutes <  0  )
       {
           hours = (endingHour - startingHour) -1 ;
           minutes = minutes + 60 ;
           System.out.println(hours +  " "  + minutes);

        }
     else  if (endingHour > startingHour&& endingTOD.equalsIgnoreCase(startingTOD) &  minutes > 0  )
       {
           hours = endingHour - startingHour;
           System.out.println(hours + " " + minutes);
        }
      else  if (endingHour > startingHour && endingTOD.equalsIgnoreCase(startingTOD) && minutes == 0  )
     {
         hours = (endingHour-startingHour);
         minutes = 0;
         System.out.println(hours + " " + minutes);
     }
   else  if (endingHour < startingHour && endingTOD.equalsIgnoreCase(startingTOD) && minutes == 0  )
     {
         hours = (endingHour-startingHour) + 12;
         minutes = 0;
         System.out.println(hours + " " + minutes);
     }
   else if ( endingHour==startingHour && minutes == 0)
   {
        hours = 12;
        minutes = 0;
        System.out.println(hours + " " + minutes);
    }
    else if (( endingTOD.equalsIgnoreCase(Pm) && startingTOD.equalsIgnoreCase(Am)) && minutes > 0)
    {
        hours = (endingHour - startingHour) + 12;
        System.out.println(hours + " " + minutes);
    }

 else if  (( endingTOD.equalsIgnoreCase(Pm) && startingTOD.equalsIgnoreCase(Am)) && minutes < 0)
       {
           hours = (endingHour - startingHour) -1 ;
           minutes = minutes + 60 ;
           System.out.println(hours +  " "  + minutes);

        }
 else if (endingHour > startingHour && ( endingTOD.equalsIgnoreCase(Pm) && startingTOD.equalsIgnoreCase(Am)) && minutes == 0)
    {
        hours = (endingHour-startingHour) + 12;
        minutes = 0;
       System.out.println(hours +  " "  + minutes);
    }
    else if (endingHour < startingHour &&( endingTOD.equalsIgnoreCase(Pm) && startingTOD.equalsIgnoreCase(Am)) && minutes == 0)
    {
        hours = (endingHour - startingHour) +24;
        minutes = 0;
       System.out.println(hours +  " "  + minutes);
    }
   else if (endingHour < startingHour &&( endingTOD.equalsIgnoreCase(Pm) && startingTOD.equalsIgnoreCase(Am)) && minutes > 0)
    {
        hours = (endingHour - startingHour) + 2;
        System.out.println(hours + " " + minutes);
    }
        }

鉴于您不能使用 Java 日历 API,您的方法虽然不是很模块化,但乍一看似乎不错。细节决定成败。

日期时间计算的技巧都是极端情况。这就是为什么没有人愿意写和维护这样的东西,甚至 Sun/Oracle 一次又一次地错了。

证明您的代码适用于所有条件将很难。您最好缩小范围并降低要求。 12 小时制还是 24 小时制?如果是 24 小时制,我们是从 0h 还是 1h 开始?我们跨越了几天?我们会被期望过午夜吗?等等

但是您的任务是以 12 或 24 为模的方式比较小时数(除非您的要求说您不必 "roll-over" 或跨越 12 或 24 小时边界。)真正的诀窍是将小时视为一系列栅栏帖子和 rails,并计算 rails。一次性错误将成为你在这里生存的祸根。

我的建议是至少使用 Java 日历 API 来仔细检查您的结果。

您可以利用内置的 Java 日期算术,而不是尝试重新发明轮子并自己实现日期减法逻辑,然后尝试涵盖所有极端情况。

像这样(将此代码复制到 TimeDifference.java 和 运行):

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Scanner;
import java.util.Calendar;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

public class TimeDifference {

    public static void elapsedTime() {
        Scanner reader = new Scanner(System.in);

        System.out.print("Enter the beginning hour: ");
        int startingHour = reader.nextInt();

        System.out.print("Enter the beginning minute(s): ");
        int startingMin = reader.nextInt();

        System.out.print("Enter AM/PM: ");
        reader.nextLine();
        String startingTOD = reader.nextLine();



        String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
        // if no ids were returned, something is wrong. get out.
        if (ids.length == 0)
            System.exit(0);

        // create a Pacific Standard Time time zone
        SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);

        // set up rules for daylight savings time
        pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
        pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY,
                2 * 60 * 60 * 1000);

        // create a GregorianCalendar with the Pacific Daylight time zone
        // and the current date and time
        Calendar startingCalendar = new GregorianCalendar(pdt);
        Calendar endingCalendar = new GregorianCalendar(pdt);
        Date trialTime = new Date();
        startingCalendar.setTime(trialTime);
        endingCalendar.setTime(trialTime);

        startingCalendar.set(java.util.Calendar.HOUR, startingHour);
        startingCalendar.set(java.util.Calendar.MINUTE, startingMin);

        if (startingTOD.equalsIgnoreCase("AM")) {
            startingCalendar.set(java.util.Calendar.AM_PM, 0);
        } else if (startingTOD.equalsIgnoreCase("PM")) {
            startingCalendar.set(java.util.Calendar.AM_PM, 1);
        } else {
            System.out.println("invalid starting AM/PM. exiting..");
            System.exit(-1);
        }

        System.out.print("Enter the ending hour: ");
        int endingHour = reader.nextInt();

        System.out.print("Enter the ending minute(s): ");
        int endingMin = reader.nextInt();

        System.out.print("Enter AM/PM:  ");
        reader.nextLine();
        String endingTOD = reader.nextLine();

        System.out.println();

        // get the supported ids for GMT-08:00 (Pacific Standard Time)

        endingCalendar.set(java.util.Calendar.HOUR, endingHour);
        endingCalendar.set(java.util.Calendar.MINUTE, endingMin);

        if (endingTOD.equalsIgnoreCase("AM")) {
            endingCalendar.set(java.util.Calendar.AM_PM, 0);
        } else if (endingTOD.equalsIgnoreCase("PM")) {
            endingCalendar.set(java.util.Calendar.AM_PM, 1);
        } else {
            System.out.println("invalid ending AM/PM. exiting..");
            /* Exit program */
            System.exit(-1);
        }

        long startingTimeMillis = startingCalendar.getTimeInMillis();
        long endingTimeMillis = endingCalendar.getTimeInMillis();
        long timeDifferenceMillis = endingTimeMillis - startingTimeMillis;

        System.out.println(String.format("Time difference between starting and ending time (in minutes and hours): %d hours, %d minutes", 
                TimeUnit.MILLISECONDS.toHours(timeDifferenceMillis),
                TimeUnit.MILLISECONDS.toMinutes(timeDifferenceMillis) - 
                TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeDifferenceMillis))
            ));

        reader.close();
    }

    public static void main(String[] args) {
        elapsedTime();
    }

}