I am attempting to add an increment method for a time class I have. I have modified the original code to only have one private integer "totalseconds" that reads the amount of seconds since midnight. That part of the code works fine but now I am trying to create a method that increments the setSecond, setMinute, and setHour. The problem (I believe) I am having is that these set methods all receive their values from totalseconds not int hour, int minute, int second as before. When I run the test for it the way I have it now I get errors at lines 36, 75 (when attempted to increment seconds via Tick method) and 101 (again only when incrementing seconds via Tick method). I have attached both the Time2 class and Time2Test app for reference.
public class Time2 {
private int totalseconds;
//no argument constructor
public Time2()
{
this(0,0,0); //invoke constructor with three arguments default to 0
}
//constructor with hour supplied minute and second default to 0
public Time2(int hour)
{
this(hour, 0, 0); //invoke constructor with 3 args
}
//constructor with hour and minute supplied seconds default to 0
public Time2(int hour, int minute)
{
this(hour, minute, 0); //invoke constructor with 3 args
}
//Time2 constructor with hour minute and second supplied also tests
public Time2(int hour, int minute, int second)
{
this.totalseconds = (hour * 3600);
this.totalseconds += (minute * 60);
this.totalseconds += (second);
}
public Time2(Time2 time)
{
//invoke constructor with 2 args
this(time.getHour(), time.getMinute(), time.getSecond());
}
// SET and GET methods start here, also Universal time conversion and check
public void setTime(int hour, int minute, int second)
{
if (hour < 0 || hour >= 24)
throw new IllegalArgumentException("Hour must be 0-23");
if (minute < 0 || minute >= 59)
throw new IllegalArgumentException("Minute must be 0-59");
if (second < 0 || second >= 59)
throw new IllegalArgumentException("Hour must be 0-59");
this.totalseconds = (hour * 3600);
this.totalseconds += (minute * 60);
this.totalseconds += second;
}
//validate and set hour
public void setHour(int hour)
{
if (hour < 0 || hour >= 23)
throw new IllegalArgumentException("Hour must be 0-23");
this.totalseconds = (hour * 3600);
}
//validate and set minute
public void setMinute(int minute)
{
if (minute < 0 || minute >= 59)
throw new IllegalArgumentException("Minute must be 0-59");
this.totalseconds += (minute * 60);
}
//validate and set second
public void setSecond(int second)
{
if (second < 0 || second >= 59)
throw new IllegalArgumentException("Second must be 0-59");
this.totalseconds += second;
}
//Get Methods start here
//Get hour
public int getHour()
{
return totalseconds / 3600;
}
//get minute
public int getMinute()
{
return (totalseconds - (3600 * getHour())) / 60;
}
//get second
public int getSecond()
{
return totalseconds - (3600 * getHour())- (60 * getMinute());
}
//Assignment 1-2 tick methods start here.
public void Tick()
{
setSecond(totalseconds ++);
if (totalseconds >= 59) incrementMinute();
}
public void incrementMinute()
{
setMinute( totalseconds ++);
if ( totalseconds >= 59) incrementHour();
}
public void incrementHour()
{
setHour ( this.totalseconds ++);
}
//convert our string to universal format (HH:MM:SS)
public String ToUniversalString()
{
return String.format(
"%02d:%02d:%02d", getHour(), getMinute(), getSecond());
}
//conver to standard format (H:MM:SS AM or PM)
public String toString()
{
return String.format("%d:%02d:%02d %s",((getHour() == 0 || getHour() ==
12) ? 12 : getHour() % 12), getMinute(), getSecond(), (getHour()
< 12 ? "AM" : "PM"));
}
}//end class Time2
public class Time2Test
{
public static void main(String[] args)
{
Time2 t1 = new Time2(); //00:00:00
Time2 t2 = new Time2(2); //02:00:00
Time2 t3 = new Time2(21, 34); //21:34:00
Time2 t4 = new Time2(12, 25, 42); //12:25:42
Time2 t5 = new Time2(t4); //12:25:42
System.out.println("Constructed with:");
displayTime("t1: all default arguments", t1);
displayTime("t2: hour specified; defaults for minute and second", t2);
displayTime("t3: hour and minute supplied second defaulted", t3);
displayTime("t4: hour minute and second supplied", t4);
displayTime("t5: Time2 object t4 specified", t5);
//attempt to initialize t6 with invalid args
try
{
Time2 t6 = new Time2(27,74,99); //all invalid values
}
catch (IllegalArgumentException e)
{
System.out.printf("%nException while initializing t6: %s%n",
e.getMessage());
}
System.out.println("Time before increment minute method");
System.out.printf("%s\n", t4.toString());
t4.Tick();
t4.incrementMinute();
t4.incrementHour();
System.out.println("Time after increment minute method");
System.out.printf("%s\n", t4.toString());
}
//display Time2 object in 24 hour and 12 hour formats
private static void displayTime(String header, Time2 t)
{
System.out.printf("%s%n %s%n %s%n", header, t.ToUniversalString(),
t.toString());
}
}
Related
So I have this assignment that is asking us to take in a String format of time in the order of HH:MM:SSAM or HH:SS:MMPM. The constraint is that it cannot run if it is in wrong format, let it be missing any form of the AM or PM, missing a number, or if it is in 24 Hour Format.
I have the whole idea down, however for my statements, it is giving me the error of:
bad operand types for binary operator '>'
incomparable types: String and int
Did I convert them improperly or am I doing something else wrong?
public static void main(String args[]) {
//Test Methods
String fullTime1 = "03:21:36AM";
secondsAfterMidnight(fullTime1);
}
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = Integer.parseInt(units[2]);
int totalSeconds = 0;
if (units[0] > 12 || units[1] > 59 || units[2] > 59) { //1st Error applies to these three, units[0] > 12 units[1] > 59 units[2] > 59
return -1;
} else if (time.equalsIgnoreCase("AM") || time.equalsIgnoreCase("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (time.equalsIgnoreCase("AM") && units[0] == 12) { //2nd Error applies to this units[0] == 12
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
You have already parsed the String values and saved them in the variables hours , minutes, seconds. Then you can use those for the check in the if.
Also the presence of AM?PM in the Integer.parseInt() will cause NumberFormatException to avoid it remove the String part from the number by using regex.
Also for checking the presence of AM/PM you can use String.contains.
Please check the reformatted code below:
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = Integer.parseInt(units[2].replaceAll("[^0-9]", ""));
int totalSeconds = 0;
if (hours > 12 || minutes > 59 || seconds > 59) {
return -1;
} else if (time.contains("AM") || time.contains("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (time.contains("AM") && hours == 12) {
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
Please note that even though you have converted the String to int, you are still comparing String with int. There would also be a RuntimeException when you do this:
int seconds = Integer.parseInt(units[2]);
As units[2] will contain 36AM. So you should be using substring() to remove the "AM/PM" part.
units is of type String and you are trying to compare it with an int hence the compile time error.
You need to convert the String to an int and then compare it, as shown below :
Integer.parseInt(units[0]) > 12
so on and so forth.
Also rather than re-inventing the wheel, you can make use of the already existing java-8's LocalTime to find the number of seconds for a particular time:
public static int secondsAfterMidnight(String time) {
LocalTime localTime = LocalTime.parse(time, DateTimeFormatter.ofPattern("hh:mm:ss a"));
return localTime.toSecondOfDay();
}
I haven't verified your logic to calculate the seconds, but this code has corrections:
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = 0;
String amPm = "";
if ( units[2].contains("AM") || units[2].contains("PM") ||
units[2].contains("am") || units[2].contains("pm") ) {
seconds = Integer.parseInt(units[2].substring(0, 2));
amPm = units[2].substring(2);
}
else {
seconds = Integer.parseInt(units[2]);
}
int totalSeconds = 0;
if (hours > 12 || minutes > 59 || seconds > 59) {
return -1;
} else if (amPm.equalsIgnoreCase("AM") || amPm.equalsIgnoreCase("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (amPm.equalsIgnoreCase("AM") && hours == 12) {
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
java.time
static DateTimeFormatter timeFormatter
= DateTimeFormatter.ofPattern("HH:mm:ssa", Locale.ENGLISH);
public static int secondsAfterMidnight(String time) {
try {
return LocalTime.parse(time, timeFormatter).get(ChronoField.SECOND_OF_DAY);
} catch (DateTimeParseException dtpe) {
return -1;
}
}
Let’s try it out using the test code from your question:
String fullTime1 = "03:21:36AM";
System.out.println(secondsAfterMidnight(fullTime1));
12096
This is the recommended way for production code.
Only if you are doing an exercise training string manipulation, you should use one of the other answers.
Link: Oracle tutorial: Date Time explaining how to use java.time.
I am trying to make a clock program using Java, and I got everything to work properly except I cannot get the program to change the negative values to 0. I also cannot get the program to set the values of hours, minutes, and seconds to 0 if they are out of range. I have a tester program that I have to use and the T1 and T2 clock values are incorrect in my code. T1 should be 0:0:0 and T2 should be 0:0:0 as well. However, when I output my code it comes out as T1 being -3:-21:-30 and T2 is 24:60:60. I know there is something wrong with my code, but I can't find the issue, if anyone would be able to help me that would be greatly appreciated. Below is my code and then the second section is the tester code that I have to use.
public class Clock
{
// instance variables
private int hours;
private int minutes;
private int seconds;
public void setHours(int newHours) {
hours = newHours;
if (hours<0 || hours > 24) {
hours = 0;
}
}
public void setMinutes(int newMinutes) {
minutes = newMinutes;
if (minutes<0 || minutes > 60) {
minutes = 0;
}
}
public void setSeconds(int newSeconds) {
seconds = newSeconds;
if(seconds<0 || seconds > 60) {
seconds = 0;
}
}
/**
* Constructor for objects of class Clock
*/
public Clock(int newHour, int newMinute, int newSecond)
{
if (newHour > -1 || newHour < 24) {
this.hours = newHour;
}
else {
setHours(hours);
}
if (newMinute > -1 || newMinute < 60) {
this.minutes = newMinute;
}
else {
setMinutes(minutes);
}
if (newSecond > -1 || newSecond < 60) {
this.seconds = newSecond;
}
else {
setSeconds(seconds);
}
}
public int getHours() {
return hours;
}
public int getMinutes() {
return minutes;
}
public int getSeconds() {
return seconds;
}
public String toString() {
return hours + ":"+minutes+":"+seconds;
}
public void tick() {
seconds = seconds +1;
if(seconds >= 60)
{
minutes ++;
seconds = 0;
}
if(minutes >= 60)
{
hours++;
minutes = 0;
}
if(hours >=24)
{
hours = 0;
}
}
}
The next piece is the tester code.
public class ClockTest {
public static void main(String [] args){
//Create some clocks and print their times
Clock c1 = new Clock(-3,-21,-30);
System.out.println("T1: "+ c1);
c1 = new Clock(24,60,60);
System.out.println("T2: "+ c1);
c1 = new Clock(3,21,30);
System.out.println("T3: "+ c1);
//Tick the clock twice and print its time
c1.tick();
c1.tick();
System.out.println("T4: "+ c1);
c1 = new Clock(3,30,59);
c1.tick();
System.out.println("T5: "+ c1);
c1 = new Clock(3,59,59);
c1.tick();
System.out.println("T6: "+ c1);
c1 = new Clock(23,59,59);
c1.tick();
System.out.println("T7: "+ c1);
c1 = new Clock(0,0,1);
c1.tick();
System.out.println("T8: "+ c1);
c1 = new Clock(1,1,1);
c1.setHours(22);
c1.setMinutes(30);
c1.setSeconds(35);
System.out.println("T9: "+ c1);
System.out.println("T10: " + c1.getHours() + ":"
+c1.getMinutes() + ":" + c1.getSeconds());
}
}
Your condition is wrong.
When you write this:
if (newHour > -1 || newHour < 24) {
You really mean this:
if (newHour > -1 && newHour < 24) {
#nicomp is correct and you should also be using >= 24 and 60 instead of >. You might consider changing the constructor for Clock to
public Clock(int newHour, int newMinute, int newSecond) {
setHours(newHour);
setMinutes(newMinute);
setSeconds(newSecond);
}
and then do all of your validation in the set methods, instead of having some validation in the set methods and some in the constructor.
What I want to do?
I want to return time and display based on user's input. Say, user enters in console starthour: 23 startminute: 45 duration (in min): 30 then the period for start time will be PM offcourse and you can see below I calculated the start time based on the above things, but issue is calculating the endtime. For example, in the above start times, the end time should become 00:15 with the period AM and not PM like start hour.
What I did?
public String toString(){
int h = (getHour()==0 || getHour()==12) ? getHour() : getHour()%12;
String period = (getHour()<12)? "AM" : "PM";
return String.format("%02d:%02d %s", h, getMinute(), period);
}
What to do?
The above formula calculates the start time and its period, correctly, but I need a similar formula that can calculate the endhour correctly based on start hour, start minutes and duration entered by the user.
Basically, above mentioned code needs to be manipulated to figure out the endhour, endminute and its period.
Note: Please don't tell about local time use for getting end time and period. Thankyou
EDIT: Here is what I did now:
public String toString(){
int endh = (getEndHour()==0 || getEndHour()==12) ? getEndHour() : getEndHour()%12;
String period = ((getEndHour() + duration) <12)? "AM" : "PM";
return String.format("%02d:%02d %s", endh, getEndHour(), period);
}
you should use 60 modulo for simplicity. here it is
public class Timer {
int hour;
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public int getMinutes() {
return minutes;
}
public void setMinutes(int minutes) {
this.minutes = minutes;
}
public void addDuration(int duration) {
hour = hour + (minutes + duration)/ 60;
minutes = (minutes + duration) % 60;
}
int minutes;
#Override
public String toString() {
int h = (getHour() == 0 || getHour() == 12) ? getHour()
: getHour() % 24;
String period = (getHour() < 12) ? "AM" : "PM";
return String.format("%02d:%02d %s", h, getMinutes(), period);
}
public static void main(String args[]) {
Timer time = new Timer();
time.setHour(23);
time.setMinutes(45);
System.out.println(time.getHour());
time.addDuration(30);
System.out.println(time.getHour());
System.out.println(time);
}
}
I am really new to programming. I am doing an assignment for my intro to Java. In my assignment, we need to find the total number of seconds since midnight and changed this number to hours, minutes and seconds to show the current time. I have small problem. when I test my code, the totalseconds show 0! any help would be appreciated. Sorry the code is a chaos
package clock;
import java.text.DecimalFormat;
import java.util.Calendar; // to get current time
public class Clock {
public static int totalseconds;
public static int seconds;
public static int minutes;
public static int hours;
public static int test;
public Clock(int hours, int minutes, int seconds ) {
setHours(hours);
setMinutes(minutes);
setSeconds(seconds);
}
// use current time
public Clock() {
Calendar c = Calendar.getInstance();
long now = c.getTimeInMillis();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
long passed = now - c.getTimeInMillis();
long secondsPassed = passed / 1000;
totalseconds = (int) secondsPassed;
}
public void tick() {
addSecond();
}
private void addSecond() {
seconds = totalseconds%60;
}
private void addMinute() {
minutes = totalseconds/60 % 60;
}
private void addHour() {
hours = totalseconds / 3600;
}
public String toString() {
DecimalFormat f = new DecimalFormat("00");
return f.format(hours) + ":" + f.format(minutes) + ":" + f.format(seconds);
}
public int getHours() {
return hours;
}
public int getMinutes() {
return minutes;
}
public int getSeconds() {
return seconds;
}
// the total number of minutes sinces midnight
public int getTotalMinutes() {
return totalseconds / 60 % 60;
}
// the total number of seconds since midnight
public int getTotalSeconds() {
return totalseconds;
}
public void setHours(int hours) {
if (hours > 23 || hours < 0) {
this.hours = 0;
}
else
this.hours = hours;
}
public void setMinutes(int minutes) {
if (minutes > 59 || minutes < 0)
this.minutes = 0;
else
this.minutes = minutes;
}
public void setSeconds(int seconds) {
if (seconds > 59 || seconds < 0)
this.seconds = 0;
else
this.seconds = seconds;
}
// reset hours, minutes and seconds to zero
public void reset() {
hours = minutes = seconds = 0;
}
public static void main(String [] args){
System.out.println("this is total seconds " + test + totalseconds );
}
}
Change main to this.
public static void main(String [] args){
Clock clock = new Clock();
System.out.println("this is total seconds " + test + totalseconds );
}
New you make an instance of Clock and the constructor is called, where all your magic happens.
I agree with what #shmosel suggested. There seems to be confusion in how to use instance variable. Further, I think you should take advantages of Java 8 methods for your time part.
class Clock {
private int totalseconds;
private int seconds;
private int minutes;
private int hours;
int test;
public Clock(int hours, int minutes, int seconds) {
setHours(hours);
setMinutes(minutes);
setSeconds(seconds);
}
// use current time
public Clock() {
LocalTime now = LocalTime.now(ZoneId.systemDefault());
totalseconds = now.toSecondOfDay();
}
public void tick() {
addSecond();
}
private void addSecond() {
seconds = totalseconds % 60;
}
private void addMinute() {
minutes = totalseconds / 60 % 60;
}
private void addHour() {
hours = totalseconds / 3600;
}
public String toString() {
DecimalFormat f = new DecimalFormat("00");
return f.format(hours) + ":" + f.format(minutes) + ":" + f.format(seconds);
}
public int getHours() {
return hours;
}
public int getMinutes() {
return minutes;
}
public int getSeconds() {
return seconds;
}
// the total number of minutes since midnight
public int getTotalMinutes() {
return totalseconds / 60 % 60;
}
// the total number of seconds since midnight
public int getTotalSeconds() {
return totalseconds;
}
public void setHours(int hours) {
if (hours > 23 || hours < 0) {
this.hours = 0;
} else
this.hours = hours;
}
public void setMinutes(int minutes) {
if (minutes > 59 || minutes < 0)
this.minutes = 0;
else
this.minutes = minutes;
}
public void setSeconds(int seconds) {
if (seconds > 59 || seconds < 0)
this.seconds = 0;
else
this.seconds = seconds;
}
// reset hours, minutes and seconds to zero
public void reset() {
hours = minutes = seconds = 0;
}
}
public class SecondsSinceMidnight {
public static void main(String[] args) {
Clock myClock = new Clock();
System.out.println("Total seconds that elapsed since midnight:" + myClock.getTotalSeconds());
System.out.println("Converted to Minutes: " + myClock.getTotalMinutes());
}
}
I am currently trying to increment my code to add a second and if the second changes the hour and minute, it will be reflected. here is my current code. I know the issue that I am having lies in the get hour method because it is the only one that isn't incrementing. Thank you for the help.
public class Time2
{
private int hour; // 0 - 23
private int minute; // 0 - 59
private int second; // 0 - 59
private int seconds;
// Time2 no-argument constructor: initializes each instance variable
// to zero; ensures that Time2 objects start in a consistent state
public Time2()
{
this( 0, 0, 0 ); // invoke Time2 constructor with three arguments
} // end Time2 no-argument constructor
// Time2 constructor: hour supplied, minute and second defaulted to 0
public Time2( int h )
{
this( h, 0, 0 ); // invoke Time2 constructor with three arguments
} // end Time2 one-argument constructor
// Time2 constructor: hour and minute supplied, second defaulted to 0
public Time2( int h, int m )
{
this( h, m, 0 ); // invoke Time2 constructor with three arguments
} // end Time2 two-argument constructor
// Time2 constructor: hour, minute and second supplied
public Time2( int h, int m, int s )
{
setTime( h, m, s ); // invoke setTime to validate time
} // end Time2 three-argument constructor
// Time2 constructor: another Time2 object supplied
public Time2( Time2 time )
{
// invoke Time2 three-argument constructor
this( time.getHour(), time.getMinute(), time.getSecond() );
} // end Time2 constructor with a Time2 object argument
// Set Methods
// set a new time value using universal time; ensure that
// the data remains consistent by setting invalid values to zero
public void setTime( int h, int m, int s )
{
setHour( h ); // set the hour
setMinute( m ); // set the minute
setSecond( s ); // set the second
} // end method setTime
// validate and set hour
public void setHour( int h )
{
hour = ( ( h >= 0 && h < 24 ) ? h : 0 );
} // end method setHour
// validate and set minute
public void setMinute( int m )
{
minute = ( ( m >= 0 && m < 60 ) ? m : 0 );
} // end method setMinute
// validate and set second
public void setSecond( int s )
{
second = ( ( s >= 0 && s < 60 ) ? s : 0 );
} // end method setSecond
// Get Methods
// get hour value
public int getHour()
{
if(minute > 59)
{
hour++;
}
return hour;
} // end method getHour
// get minute value
public int getMinute()
{
if(second > 59)
{
minute++;
}
if(minute > 59)
{
minute = 00;
}
return minute;
} // end method getMinute
// get second value
public int getSecond()
{
if(second > 59)
{
second = 00;
}
return second++;
} // end method getSecond
// convert to String in universal-time format (HH:MM:SS)
public String toUniversalString()
{
return String.format(
"%02d:%02d:%02d", getHour(), getMinute(), getSecond() );
} // end method toUniversalString
// convert to String in standard-time format (H:MM:SS AM or PM)
public String toString()
{
return String.format( "%d:%02d:%02d %s",
( (getHour() == 0 || getHour() == 12) ? 12 : getHour() % 12 ),
getMinute(), getSecond(), ( getHour() < 12 ? "AM" : "PM" ) );
} // end method toString
} // end class Time2
The results that I am getting from my test app are:
public class Time2Test
{
public static void main(String[] args)
{
Time2 t1 = new Time2(); // 00:00:00
Time2 t2 = new Time2(2); // 02:00:00
Time2 t3 = new Time2(21, 34); // 21:34:00
Time2 t4 = new Time2(12, 59, 59); // 12:25:42
Time2 t5 = new Time2(t4); // 12:25:42
System.out.println("Constructed with:");
displayTime("t1: all default arguments", t1);
displayTime("t2: hour specified; default minute and second", t2);
displayTime("t3: hour and minute specified; default second", t3);
displayTime("t4: hour, minute and second specified", t4);
displayTime("t5: Time2 object t4 specified", t5);
// attempt to initialize t6 with invalid values
try
{
Time2 t6 = new Time2(27, 74, 99); // invalid values
}
catch (IllegalArgumentException e)
{
System.out.printf("%nException while initializing t6: %s%n",
e.getMessage());
}
}
// displays a Time2 object in 24-hour and 12-hour formats
private static void displayTime(String header, Time2 t)
{
System.out.printf("%s%n %s%n %s%n",
header, t.toUniversalString(), t.toString());
}
} // end class Time2Test
Output:
Constructed with:
t1: all default arguments
00:00:00
12:00:01 AM
t2: hour specified; default minute and second
02:00:00
2:00:01 AM
t3: hour and minute specified; default second
21:34:00
9:34:01 PM
t4: hour, minute and second specified
12:00:00
12:00:01 PM
t5: Time2 object t4 specified
12:59:59
12:00:00 PM
In this piece of code:
getMinute(), getSecond(), ( getHour() < 12 ? "AM" : "PM" )
If minute is greater than 59, the getMinute method will change minute to 0. Then when getHour is called, minute is 0, so hour isn't incremented.
As others have stated, do not modify variables in getters. It causes all kinds of havoc.