views:

63

answers:

2

I'm working on an Android application that tracks time durations of tasks. Internally, it saves these durations as a float representing how many hours were spent on the task. So 30 minutes would be 0.5, 1 hour would be 1, etc. I've got all that code working great, along with code to convert these into hh:mm format for easier reading.

However, there's also an aspect where the user can manually change this value using a string input box. The following inputs should all be considered valid:

"1:30" => 1.5 "1.83" => 1.83 "0.5" => 0.5

I don't care if users enter something like "0:90", which would be 1.5 hours.

This is my current (untested) solution. Just wondering if there's a better way to go about this:

public static float HoursToFloat(String tmpHours) {
    float result = 0;
    tmpHours = tmpHours.trim();

    // Try converting to float first
    try
    {
        result = Float.parseFloat(tmpHours);
    }
    catch(NumberFormatException nfe)
    {
        // OK so that didn't work.  Did they use a colon?
        if(tmpHours.contains(":"))
        {
            int hours = 0;
            int minutes = 0;
            int locationOfColon = tmpHours.indexOf(":");
            hours = Integer.parseInt(tmpHours.substring(0, locationOfColon-1));
            minutes = Integer.parseInt(tmpHours.substring(locationOfColon+1));
            result = hours + minutes*60;
        }
    }

    return result;
}
+1  A: 

That pretty much looks right to me. Only other thing I could think of is if you wanted to take advantage of autoboxing then you could write the first part as

public static float HoursToFloat(String tmpHours) throws NumberFormatException {
     float result = 0;
     tmpHours = tmpHours.trim();

     // Try converting to float first
     try
     {
        result = new Float(tmpHours);
     }
     catch(NumberFormatException nfe)
     {
         // OK so that didn't work.  Did they use a colon?
         if(tmpHours.contains(":"))
         {
             int hours = 0;
             int minutes = 0;
             int locationOfColon = tmpHours.indexOf(":");
             try {
                  hours = new Integer(tmpHours.substring(0, locationOfColon-1));
                  minutes = new Integer(tmpHours.substring(locationOfColon+1));
             }
             catch(NumberFormatException nfe2) {
                  //need to do something here if they are still formatted wrong.
                  //perhaps throw the exception to the user to the UI to force the user
                  //to put in a correct value.
                  throw nfe2;
             }

             //add in partial hours (ie minutes if minutes are greater than zero.
             if(minutes > 0) {
                 result = minutes / 60;
             }

             //now add in the full number of hours.
             result += hours;
         }
     }

     return result;
 }

Of course, this is not really all that different. Just allows you to set as Objects and then manipulate like primitives. Otherwise what you have looks pretty good. I'd use parenthesis on the calculation at the end. I know that mulitiplication is a higher order of operation than addition and any good Java developer should know that. But the parenthesis makes it clearer to the reader/developer who comes along later and who may be a newbie to Java.

Also, you would need another try catch below, because you could bomb on the Integer converts too. Because you are bringing in a String, you can't guarantee that the user won't put in something like 'asinboinseuye:ysousieu'. Yes, you can protect against this in the UI (to a point), but you should still probably put the protection in the method as I show above. Then if for whatever reason it still isn't numeric, you can throw that to the UI and then present the user a message telling them to input a number in the formats that you find acceptable.

Otherwise, looks great.

Chris Aldrich
Wow, thanks for the great example and advice! This is definitely what I was looking for :)
Colin O'Dell
Edited the code presented above per comments from Gintautas.
Chris Aldrich
+1  A: 

Your approach is mostly OK, although you have a pile of bugs in there; if the input is not a float and does not contain a colon, your function will return 0, and you should divide minutes by 60, not multiply.

Gintautas Miliauskas
Thanks for catching those :) I don't have access to the project right now, so I wasn't able to test it.
Colin O'Dell