0

Before I had asked a question about subtracting time and I thought I had it. However as I was debugging, several bugs appeared. Basically what I am asking is to create a punch clock, but I can't use the Java Calendar API.

Users will input start times and the time they punched out and it will calculate the difference between the times.

Mine is not working very well and I don't know why. For example, If 4:00am is the start and 12:00am is the end, 8 hrs 00 min is returned. That is incorrect. I thought I created an if statement for the possibilities.

Here is my code:

     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);
    }
        }
FThompson
  • 28,352
  • 13
  • 60
  • 93
DaBom
  • 33
  • 5
  • 1
    Define *not working very well*; what is the problem(s) you're having? – Paul Richter Jan 09 '15 at 21:14
  • Well I enter sample times to test it. 8 14 am to 2 47 pm returns 6 hours and 33 minutes. I want it to return 5 hours and 27 minutes but it doesnt. I thought I created a loop that covered everything – DaBom Jan 09 '15 at 21:15
  • 9
    Huh? From 8 14 am to 2 47 pm it's 6 hours and 33 minutes... Your program is working correctly. – m0skit0 Jan 09 '15 at 21:20
  • I'm curious, you ask the user for `am` or `pm`, and then you call `nextLine()` twice. Why? – Drew Kennedy Jan 09 '15 at 21:20
  • That is because without it, it wont read integers afterwards from the user – DaBom Jan 09 '15 at 21:21
  • 1
    Is the assumption here that you can't use the Java Calendar API? –  Jan 09 '15 at 21:21
  • Yes sir/ma'am. Its supposed to be done using if statements. – DaBom Jan 09 '15 at 21:23
  • also m0skit0 it is 5hrs and 27 mins – DaBom Jan 09 '15 at 21:23
  • With times, you count "fence rails" not "fence posts". You are counting wrong. Validate with a tool like this: http://www.easysurf.cc/tspan.htm (Or use the Calendar API to double-check your math) If you are counting in your head, in this case, start counting at 9AM, counting up to 2PM, modulo 12, or use a 24 hour clock. –  Jan 09 '15 at 21:26
  • 2
    @DaBom, time to bust out your fingers and count – user1231232141214124 Jan 09 '15 at 21:27
  • @DaBom No. From 8 to 2 (14) it's 6 hours, from 14 to 47, it's 33 minutes. So 6 hours and 33 minutes. I don't know from where you get 5hrs and 27 mins. 8:14 + 5:27 = 13:41 (1:41 pm). – m0skit0 Jan 09 '15 at 21:28
  • 1
    for time difference calculations I would suggest using the new Time-API of java 8 since all previous implementations had serious bugs – mschenk74 Jan 09 '15 at 21:28
  • Oh im sorry guys is that. Also I have to do it in loops not Time API. It still doesnt work for times like 4 am to 12 am. I have a statement for it though. I just cant figure it out and it is driving me insane – DaBom Jan 09 '15 at 21:30
  • I am pretty sure you supposed to use calendar. – Jama Djafarov Jan 09 '15 at 21:31
  • @DaBom As I said, there's nothing to figure out. Your program works correctly. Your time calculations are the wrong ones. – m0skit0 Jan 09 '15 at 21:31
  • No i am not. It is an extra credit assignment for the class I am in. I have an 84 and that point ill get off of this will boost me to a B. It just sucks Ive done all this work and I have crashed into a wall. – DaBom Jan 09 '15 at 21:32
  • The difference between 8:14 AM and 2:47 PM is 6:33. @DaBom is doing it the wrong direction in his head. The difference between 2:47 and 8:14 (ignore AM/PM) is 5:27. 6:33 is the correct answer if 8:14 is the start time and 2:47 is the end time. – digitaljoel Jan 09 '15 at 21:39
  • I understand that now. All of that is good. I appreciate the clarification and have edited the question that poses a new problem – DaBom Jan 09 '15 at 21:40
  • @jdv You seem to have accidentally overriden OP's edits clarifying his issue. Be sure to notice when another edits occurs while you are mid-edit to avoid this issue. I've fixed the question to reflect the overriden changes. – FThompson Jan 09 '15 at 21:59
  • @Vulcan, we have to assume that the system will handle concurrent edits -- there certainly was no clear indication to me that there were concurrent edits. –  Jan 10 '15 at 01:18

2 Answers2

1

Given that you cannot use the Java Calendar API, your approach, while not very modular, looks sound at first glance. The devil is in the details.

The trick with date-time calculations are all the corner-cases. This is why no one wants to write and maintain such things, and even Sun/Oracle got it wrong again and again.

Proving your code works for all conditions is going to be hard. You are better off reducing scope and lowering requirements. 12 or 24 hour clocks? If 24-hour, do we start at 0h or 1h? Are we spanning days? Will we be expected to cross midnight? etc.

But your tasks is to do compare hours in a modulo 12 or 24 manner (unless your requirements say you don't have to "roll-over" or cross 12 or 24 hour boundaries.) And the real trick is to think of hours as a series of fence posts and rails, and count the rails. one-off errors are going to be the bane of your existence here.

My advice is to use the Java Calendar API at least to double check your results.

  • I have no idea how to use that. I think I am just going to submit and hope for the best. My head hurts so bad right now haha – DaBom Jan 09 '15 at 21:42
  • I agree with jdv's advice. Please see my code below for sample. It is using Java Calender API. – user1521213 Jan 09 '15 at 23:07
0

Instead of trying to reinvent the wheel and implement date subtraction logic yourself and then try to cover all the corner cases, you can leverage built in Java Date Arithmetic.

Something like this (copy this code into TimeDifference.java and run):

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

}
user1521213
  • 139
  • 1
  • 6
  • Borrowed some of the code from stackover answer below:http://stackoverflow.com/questions/625433/how-to-convert-milliseconds-to-x-mins-x-seconds-in-java – user1521213 Jan 09 '15 at 23:04