tags:

views:

109

answers:

5
package timeToys;

import java.util.regex.Pattern;


**
 * A DayTime is an immutable object that stores a moment of day represented in
 * hour, minutes and seconds. Day or year are not defined.
 * 
 * @author marius.costa <[email protected]>
 */

public class DayTime {`enter code here`

    private int hour;// hour of the day
    private int minute;// minute of the hour
    private int second;// second of the minute
    private String time;// time as string

    private static final String TIME_LONG_FORMAT = "([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]";
    private static final String TIME_SHORT_FORMAT = "([01]?[0-9]|2[0-3]):[0-5][0-9]";

    /**
     * Class private constructor that creates new objects using inner builder.
     * 
     * @param timeBuilder - builder for new DayTime objects defined as inner class.
     */
    private DayTime(Builder timeBuilder) {
        this.hour = timeBuilder.hour;
        this.minute = timeBuilder.minute;
        this.second = timeBuilder.second;
        this.time = timeBuilder. time;
    }

    public int getHour() {
        return hour;
    }

    public int getMinute() {
        return minute;
    }

    public int getSecond() {
        return second;
    }

    @Override
    public String toString() {
        return time;
    }

    /**
     * Builder is a inner class that creates new DayTime objects based on int params
     * (hour, minute, second), or by parsing a String param formated as
     * 'HH:mm' or 'HH:mm:ss'.
     */
    public static class Builder {
        private int hour = 0;
        private int minute = 0;
        private int second = 0;
        private String time;

        /**
         * Constructor that creates a Builder from a String param formated as
         * 'HH:mm' or 'HH:mm:ss'.
         * @param time - must be formated as 'HH:mm' or 'HH:mm:ss'.
         */
        public Builder(String time) {
            this.time = time;
        }

        /**
         * Creates a DayTime object from the String {@link #time}.
         * The String {@code time} is innitialy parsed to validate time
         * in 24 hours format with regular expression.
         * If not, RuntimeExceptions will be thrown.
         *  
         * 
         * @return DayTime 
         * @throws IllegalArgumentException if the string isn't right formated.
         * @throws NumberFormatException if int values cannot be extracted from String time.  
         */
        public DayTime createTime() {
            String[] timeUnits = time.split(":");
            if(Pattern.compile(TIME_SHORT_FORMAT).matcher(time).matches()) {
                this.hour = Integer.parseInt(timeUnits[0]);
                this.minute = Integer.parseInt(timeUnits[1]);
            } else if(Pattern.compile(TIME_LONG_FORMAT).matcher(time).matches()) {
                this.hour = Integer.parseInt(timeUnits[0]);
                this.minute = Integer.parseInt(timeUnits[1]);
                this.second = Integer.parseInt(timeUnits[2]);
            } else {
                throw new IllegalArgumentException("Invalid time format" +
                " (Expected format: 'HH:mm' or 'HH:mm:ss').");
            }
            return new DayTime(this);
        }
    }
}
+9  A: 

dont do it. Resist all temptation to write your own date / time code. It will bite you

use standard date class - even tho it seems a waste

pm100
+1  A: 
DayTime d1 = new DayTime(8000, -1, 557); // :(
DayTime d2 = new DayTime(8000, -1, 557);
d1.equals(d2); // :(
z5h
+1 System.out.println(d1);
Totophil
I've removed the public constructor with int parameters, which I've forgot to validate. Thanks z5h :).
marcos
@marcos, is there any good reason why DateTime should not be made immutable?
Totophil
I've just answered that setters shouldn't be there. Class was intended to be immutable, but I've also generates Setters together with Getters, by mistake. Thanks for your remark.
marcos
+7  A: 

Use JodaTime.

BalusC
Up Vote. Nuff Said.
Joel
+1  A: 

You may consider add the methods:

equals()

hash()

and implement the Comparable interface

int compareTo( Object other )

Also, it is recommendable to make it immutable.

For instance if you use this class to check if something has to happen:

 class Remainder {
     private String what;
     private DateTime when;


     public static Remainder remindMe( String what, DateTime when ) {
         Reminder r = new Reminder();
         r.what = what;
         r.when = when;
     }

     public boolean isTimeAlready() {
          //return DateTime.Builder.createTime().compareTo( this.when ) > 0;
          // implemented somehow 
          return isCurrentTimeGreaterThan( this.when ); // assume it return true if current time is after "when"
     }
  }

If you use it like this:

  DateTime atSix = new DateTime( 18, 0, 0 );

  Reminder reminder = Reminder.remindMe("Go for the milk", atSix );

And the hour is changed ( by mistake of course )

  atSix.setHour( 1 );

It won't be any use to the "Reminder" object that the variable when is private, because it's reference is kept outside and doesn't have the control over it, hence it become unreliable.

That would be a very strange bug you may introduce. Using immutable objects is less error prone. That's why core objects in Java like String, Integer, and lots others are immutable.

If you can read this book: Effective Java it will turn 180 deg you Java perspective.

OscarRyz
Absolutely agree. Setters shouldn't be there. I've also removed the public constructor that takes int values.
marcos
A: 

I've updated the code with some suggested changes. It looks much better now, I suppose :). Many thanks to all that have answered.

marcos