How can I repeat the process to display the current time? - java

I'm trying to create a clock programm with customizable options but since I'm a beginner I'm running into some problems. I tried using the DigitalClock project but there's too many things in it for me right now
I looked into Timer and ScheduledExecuterService but I don't know how to use and where to place them.
I also tried to set a color to the background but the error was that it could be over ran.
How can I repeat the process in milliseconds, add a background and make the code lighter ?
public Clock() {
initComponents();
Calendar cal = new GregorianCalendar();
int second = cal.get(Calendar.SECOND);
int minute = cal.get(Calendar.MINUTE);
int hour = cal.get(Calendar.HOUR_OF_DAY);
/////////////////////////////////////////////////////////////
if (second < 10){
time.setText(" "+hour+": "+minute+":0"+second+"");
}
else if (minute < 10){
time.setText(" "+hour+":0"+minute+": "+second+"");
}
else if (hour < 10){
time.setText("0"+hour+": "+minute+": "+second+"");
}
else if (hour < 10 & minute < 10){
time.setText("0"+hour+":0 "+minute+": "+second+"");
}
else if (minute < 10 & second < 10){
time.setText(" "+hour+":0"+minute+":0"+second+"");
}
else if (hour < 10 & minute < 10 & second < 10){
time.setText("0"+hour+":0"+minute+":0"+second+"");
}
else {
time.setText(hour + " : " + minute + " : " + second+"");
}
////////////////////////////////////////////////////////////////
}

If you want to make it simple then you can simple do the following:
public static void main (String[] args) throws Exception
{
final SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss:SSS");
while(true) {
System.out.println(sf.format(new Date()));
Thread.sleep(1);
}
}
But this might miss a millisecond entry in between. For example, it might go directly to 310 after 308 and miss 309 in between. But since we are talking about 1/1000th of a second, in real life it is very unlikely to be noticed.
Your code will reduce to something like following:
public Clock() {
public static void main (String[] args) throws Exception {
initComponents();
final SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss:SSS");
while(true) {
time.setText = sf.format(new Date());
Thread.sleep(1);
}
}
}

final SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss:SSS");
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
System.out.println(sf.format(new Date()));
}
}, 0 , 1000000);
Will repeat in 1 ms.

Related

Problem syncing custom timer to system clock

I have a custom timer that I'm keeping synced to the system clock. It's working fine for one minute intervals, but I also need it to sync to 36 second intervals (for updating fields when the user wants times displayed in decimal hours). Inside the Runnable I recalculate the adjustment (accurate enough for my needs) for the next minute, but can't find a way to conveniently deal with the different offsets needed for 36 seconds.
EDIT
private static class DecimalTimer extends TimerClass {
final int[] seconds = new int[101];
private boolean keepRunning = true;
private Runnable mRunnable;
#Override
void kill() {
keepRunning = false;
}
#Override
Runnable getRunnable() {
return mRunnable;
}
DecimalTimer() {
final int[] counter = new int[1];
for (int i = 0, j = 0; i < 3600; i += 36, j++) {
seconds[j] = i;
}
mRunnable = new Runnable() {
#Override
public void run() {
if (!keepRunning)
return;
final Calendar c = Calendar.getInstance();
int hourSeconds = c.get(Calendar.MINUTE) * 60 + c.get(Calendar.SECOND);
for (counter[0] = 0; counter[0] < 100; counter[0]++) {
if (seconds[counter[0]] > hourSeconds) {
c.add(Calendar.SECOND, seconds[counter[0]]);
break;
}
}
long adjustedDelay = (c.getTimeInMillis() - System.currentTimeMillis()) % 36000;
for (IntervalTimer listener : sListeners) {
listener.updateTime();
}
sHandler.postDelayed(this, adjustedDelay);
}
};
}
}
This edit fires every 36 seconds, but I need to get it to sync to 36 seconds on the clock (ie: 12:00:00, then 12:00:36 .. 12:01:12 .. 12:01:48)
Overthinking things as usual, this is what I came up with. It's accurate enough for what I need, but if anyone has an improvement for accuracy (It's a little off when it executes with 900ms or more) it'd be appreciated.
DecimalTimer() {
mRunnable = new Runnable() {
#Override
public void run() {
if (!keepRunning)
return;
final Calendar c = Calendar.getInstance();
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
do {
c.add(Calendar.SECOND, 36);
} while (c.getTimeInMillis() < System.currentTimeMillis());
long adjustedDelay = (c.getTimeInMillis() - System.currentTimeMillis()) % 36000;
for (IntervalTimer listener : sListeners) {
listener.updateTime();
}
sHandler.postDelayed(this, adjustedDelay);
}
};
}

Java Clock Program

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.

Running a counter thread in the background during a game

I am wondering the best way to keep a timer going in the background while a game is played.
I am programming a version of the HiLo game (in Java), which gives a user a certain amount of time to determine a number. If a guess is not correct, the game will tell the user whether the name is too high or too low.
I'm keeping track of time using System.currentTimeMillis() and seeing how much time has elapsed. This seems to work well, and so far I have been checking to see how much time has elapsed each time a new number is entered. For example, currently the app output looks like this:
Welcome to HiLo!
You have 10 seconds to guess a number I'm thinking of between 1 and 100.
> 67
Too high.
> 29
Too low.
Half of your time is gone! Only 5 seconds remains!
> 37
Too high.
> 33
Oops! Time is up - try again.
As you can see, currently, it can only check when I enter a new number how much time is passed.
I have tried creating a thread to start with a timer, however, when I start it, it keeps counting until the time is exhausted, without going on to the thread.run(int guess) which will be run when there is a new guess. I want to be able to still make guesses while the counter runs. Here is my attempt at a new implementation for thread.start():
public void start(int time_sent) throws InterruptedException {
time = time_sent;
startTime = (System.currentTimeMillis() / 1000);
while (1==1) {
long elapsed = ((System.currentTimeMillis() / 1000) - (startTime));
if (elapsed >= (time)) {
System.out.println("Oops! Time is up - try again.");
System.exit(0);
}
else if (elapsed >= (time/2) && !halfWarning) {
System.out.println("Half of your time is gone! Only " + (time/2) + " seconds remains!");
halfWarning = true;
}
}
}
How can I continue running this counter in the background?
This is one more approach:
public void game() {
Scanner scanner = new Scanner(System.in);
int time = 10; // sec
message("You have " + time + " seconds to guess...");
new Thread(new Background(System.currentTimeMillis() / 1000, time)).start();
while (true) {
String s = scanner.next();
if (s.equals("55")) {
message("You win");
System.exit(0);
} else {
message("try again...");
}
}
}
private void message(String str) {
System.out.println(str);
System.out.print("> "); // monit
}
You start 1 thread with behavior implemented in Background class. Next you enter while loop to capture user inputs. The Background thread works in background...
private class Background implements Runnable {
private long startTime;
private long time;
private boolean halfWarning;
private Background(long startTime, long time) {
this.startTime = startTime;
this.time = time;
}
#Override
public void run() {
while (true) {
long now = System.currentTimeMillis() / 1000;
long elapsed = now - startTime;
if (elapsed >= (time / 2) && !halfWarning) {
message("\n Half of your time is gone! Only " + (time / 2) + " seconds remains!");
halfWarning = true;
}
if (elapsed >= time) {
message("\n Oops! Time is up - try again.");
System.exit(0);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//ignore
}
}
}
}
Use a ScheduledExecutorService to execute concurrent actions in the future:
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> half = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Half of your time is gone!");
}
}, time / 2, TimeUnit.SECONDS);
ScheduledFuture<?> full = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Oops! Time is up - try again.");
// System.exit(0) ?
}
}, time, TimeUnit.SECONDS);
// check
if (input == toGuess) {
half.cancel();
full.cancel();
}
You could have a Timer thread that prints out these messages and shuts down the listening program.
It might inspire you :
public static class Game extends TimerTask {
private long start;
private long end;
public Game(long end) {
super();
this.start = System.currentTimeMillis();
this.end = end;
}
#Override
public void run() {
while (System.currentTimeMillis() - start < end)
System.out.println(System.currentTimeMillis());
}
}
public static void main(String[] args) {
TimerTask task = new Game(10000);
Timer timer = new Timer();
timer.schedule(task,0);
}

Method not working properly

This is a method that i made for my comp sci class:
public Time (int y, int x)
{
minute = x;
hour = y;
if (minute>59 || minute<0)
{
minute = 0;
}
if (hour>=24 || hour<0)
{
hour=0;
}
}
void addOne()
{//Adds one to the minute. Still in military time
minute++;
if (minute == 60) //Makes minute never exceeds 59 minutes. Hour is added 1 and minute is set to 0
{
minute = 0;
hour++;
if (hour==24)
{
hour=0;
}
}
}
public String convert()
{//Converts to standard time with am and pm
String timer = null;
int counter = 0;
if (hour<12)
{
if (hour<9)
{
if (minute>9)
{
timer = "0"+hour+":"+minute+" A.M.";
}
if (minute<10)
{
timer = "0"+hour+":0"+minute+" A.M";
}
}
if (hour>9)
{
if (minute>9)
{
timer = ""+hour+":"+minute+" A.M.";
}
if (minute<10)
{
timer = ""+hour+":0"+minute+" A.M";
}
}
}
if (hour ==12)
{
if (minute>9)
{
timer = ""+hour+":"+minute+" P.M.";
}
if (minute<10)
{
timer = ""+hour+":0"+minute+" P.M";
}
}
if (hour>12)
{
hour-=12;
if (hour ==12)
{
if (minute>9)
{
timer = ""+hour+":"+minute+" A.M.";
}
if (minute<10)
{
timer = ""+hour+":0"+minute+" A.M";
}
}
if (hour<9)
{
if (minute>9)
{
timer = "0"+hour+":"+minute+" P.M.";
}
if (minute<10)
{
timer = "0"+hour+":0"+minute+" P.M";
}
}
if (hour>9)
{
if (minute>9)
{
timer = ""+hour+":"+minute+" P.M.";
}
if (minute<10)
{
timer = ""+hour+":0"+minute+" P.M";
}
}
}
return timer;
}
And this is the code that is suppose to run:
Time time7 = new Time(23,59);
System.out.println("\ntime7: " + time7);
System.out.println("convert time7: " + time7.convert());
time7.addOne();
System.out.println("increment time7: " + time7);
System.out.println("convert time7: " + time7.convert());
I get the output as:
time7: 2359
convert time7: 11:59 P.M.
increment time7: 1200
convert time7: 12:00 P.M
But I need the output to be:
time7: 2359
convert time7: 11:59 P.M.
increment time7: 0000
convert time7: 12:00 A.M
All other parts to the program works just fine, until i get to time7.
Starting with hour set to 23, then after this code:
if (hour>12)
{
hour-=12;
...
what is the value of hour?
I'm afraid your code is needlessly complex, even if you fix the bug. Look at the String.format() method for a much better way of formatting numbers for output that does not require you to handle all those "special cases" separately.
After you increment and before you convert, you could add:
hour %= 24;
If hour is 24, it would then become 0.

Java While Loop checks the time but not performing a method

In this code a while loop is supposed to check the time, and if the time is equal to 7 PM, then display a message box.
public void actionPerformed(ActionEvent arg0) {
Enable.setEnabled(false);
Date d = new Date();
int hrs = d.getHours();
int mins = d.getMinutes();
while((1 + 1) == 2) {
if(hrs == 19 && mins == 21) {
JOptionPane.showMessageDialog(frame,
"It's 7:21 PM!",
"Alerts",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
break;
}
}
}
Pushing a button will do that code. If you push the button before it is 7 PM, the GUI will freeze (I don't care about that), and when it turns to 7 PM, it won't display the message box. If you click the button when it is 7 PM, then it will display the message box...
Instead of doing while((1 + 1) == 2) to get an infinite loop, you can just do: while(true) or for(;;)
And this question is unanswerable without any further information or code about your hrs and mins variables
You need to update hrs and mins in your loop otherwise the initialization of them, I assume at the time of pushing the button will always hold the time when the button was pushed.
This is why it works when pushed at 7pm but otherwise will not.
So do something like this
while(true) //Equivalent to what you had
{
if(hrs == 19 && mins == 00) {
JOptionPane.showMessageDialog(frame,
"It's 7:00 PM!",
"Time Alert",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
break;
}
//Refresh your hrs and mins here
Calendar calendar = GregorianCalendar.getInstance(); // Probably dont really want to actually get an instance every time
hrs = calendar.get(Calendar.HOUR_OF_DAY);
mins = calendar.get(Calendar.MINUTE);
}
I'm thinking you're using 1+1=2 to have a continuous loop. you could use while(true){...} instead.
Also, the while loop wouldn't be practical for this case. There is an example on this page that does something similar (Alarm Clock): http://www.ibm.com/developerworks/java/library/j-schedule/index.html
this was their example. I updated it to suite your task.
public class AlarmClock {
private final Scheduler scheduler = new Scheduler();
private final SimpleDateFormat dateFormat =
new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
private final int hourOfDay, minute, second;
public AlarmClock() {
this.hourOfDay = 19;
this.minute = 0;
this.second = 0;
}
public void start() {
scheduler.schedule(new SchedulerTask() {
public void run() {
soundAlarm();
}
private void soundAlarm() {
JOptionPane.showMessageDialog(frame,
"It's 7:00 PM!",
"Time Alert",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
// Start a new thread to sound an alarm...
}
}, new DailyIterator(hourOfDay, minute, second));
}
public static void main(String[] args) {
AlarmClock alarmClock = new AlarmClock();
alarmClock.start();
}
}
Hope it helps.

Categories

Resources