I have a piece of code that has to be executed at a particular time every day. If I schedule it to be executed at 9PM everyday, then it has to work even during the switching of Day light saving.
Which Java API can be used to achieve this?
int ONE_DAY = 1000 * 60 * 60 * 24;
Timer timer = new Timer();
timer.schedule(myTimerTask, startTime, ONE_DAY); // startTime is 9PM of current day
I've used the above approach which will not take care of DST.
If you need to schedule based on calendrical values - rather than just elapsed time, basically - then you either need to wrap Timer in your own code, or use a library which has already been built for this purpose. In this case, I suspect the Quartz Scheduler is your best bet.
Given how complicated date/time can be, I'd generally recommend using a well-known library over rolling your own code. Note that this often doesn't mean that you can get away without thinking about complicated aspects of the problem - it just means that you should be able to express your requirements fairly simply. For example, in the context you're looking at, you should consider:
What time zone do you want the "9pm" to be expressed in? Is it the system default time zone? Some other specific one? Multiple different time zones for different tasks?
What do you want to happen if the scheduled time doesn't occur, or occurs twice on one day? You're likely to be okay with 9pm, but if you had (say) 1.30am in the UK time zone, when the clocks go forward into BST, that will be skipped for that day - and when the clocks go back into GMT, it will occur twice.
How do you want to handle the system clock being changed, either manually or automatically?
You can schedule the timer to run the task each hour and let the task decide when to actually run using Calendar
Related
Using Java Flow Framework for SWF.
Any way to schedule an activity for a specific time in SWF?
Let's say, send run the "sendNotification" at 22nd Oct 2017 9:00 AM.
The examples allow to create timer with a delay, but not for the specified time.
Even though I can calculate the delay, based on the current time stamp and the target time when the event is needed to be fired, but how can I get the current time during workflow execution, since if you try to get the current system time in workflow decider, it creates non-determinism in workflow and it fails.
Date currentDate = new Date();
long sysTimeInSeconds = (currentDate.getTime() / 1000);
System.out.println("System Time : " + sysTimeInSeconds);
Promise<Void> timer = clock.createTimer((timeStampInSeconds - sysTimeInSeconds));
[ The above code is not allowed since we are using current time from system]
The current time of workflow clock, returns the start time of the workflow, which is of no use to me.
So how I can schedule an activity for a particular time ?
Use the WorkflowClock. It returns the correct deterministic current time which is the time of the decision being replayed.
Here is the line of code that updates clock to the current decision time.
I would like to set arbitrary time in application. Time is downloaded from server in milliseconds format- it should be independent from locale and other system preferences.
But application reacquire thread safety solution, and object like standard not thread safety Calendar object.
Whats is the best way?
Today I use:
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(serverTime);
But is not good way for me beacuse, is't thread safe.
tl;dr
Program have to contain own internal clock fetching time from external server. Clock must be thread-safe.
The time in milliseconds that a Java application uses is
the specified number of milliseconds since the standard base time
known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
This number is based on the GMT time zone. If you need to print it in another time zone you can use any formatting class you want, say SimpleDateFormat. If you need to make the variable that holds it thread safe, just synchronize on it, possibly by wrapping it in a class.
public class TimeInMillis {
private volatile long time;
public void setTime(long time) {this.time = time;}
public time getTime() {return time;}
}
Whenever you need to display it, just get the TimeInMillis object, get the time and create a Calendar object with it. Then use a formatting class to print the time in the format, locale, timezone, you require.
Time is downloaded from server in milliseconds format- it should be independent from locale and other system preferences
That isn't "time". That is a timestamp, meaning a particular time value reported by a particular piece of software at a particular point in time.
Now, if you are trying to say that, in future communications with this server, you want to translate time as reported by the device into the timebase as known by the server, that makes at least a bit of sense. In that case, you compute the delta between the device time when you receive the timestamp and the time value in the timestamp itself. Then, you apply that delta to future times you report back to the server.
Program have to contain own internal clock fetching time from external server
That makes no sense whatsoever.
In this universe, based on our current knowledge of physics, time is continuous and linear. Time does not change only when you are "fetching time from an external server". Again, what you are "fetching... from an external server" is a timestamp, a statement of what the clock on the server thought the time was at the time you made the request. You can use that timestamp for comparison purposes with other timestamps from that server, and you can use that timestamp to compare to the device's current time to determine the difference.
However, you cannot create hardware in Java code, and so you cannot create "internal clock" in Java code. The only clock is the device's clock. As noted earlier, you can translate the device's clock's time to the timebase of the server by applying the aforementioned difference, but the passage of time is still being marked by the device's own clock.
Since the difference is going to be an int or long, you can use AtomicInteger or AtomicLong if you are concerned about multiple threads working with the value at once.
I would just the the time in milli-second with GMT (BTW computers don't support UTC as such)
long serverTime = System.currentTimeMillis(); // millis since 1/1/1970 GMT.
To get/set this in a thread safe manner you can make it volatile
BTW Calender is pretty slow even on a PC. I would avoid using it on a phone.
Said now is 6 o'clock, I have a Timer and scheduled a TimerTask at 10 o'clock. After that, System DateTime is adjusted by an other service (ntp for example) to 9 o'clock. I still want my TimerTask will be fired at 10 o'clock but it does not, Timer still wait for next 4 hours and fire my TimerTask. What should I do in this situation?
Firstly, you're already in a pretty nasty mess if your clock is out by 4 hours. Typically time adjustments will only be by milliseconds or seconds - or occasionally a minute or two, if the machine hasn't been online for a very long time. One option would be to check that the time is reasonably accurate by making your own NTP call before setting the timer.
Another option is to make a reasonably regularly-invoked timer - for example once every minute or five minutes - which checks the time and then optionally takes action. It's slightly less efficient, but I wouldn't expect the impact of waking up a single thread to perform a simple check once a minute or so would have a significant effect on performance. You should adjust the regularity of the check based on how accurately you need your timer to fire, and how little performance impact you need it to have.
I am using Jboss5.1.x, EJB3.0, Quartz 1.8
I have System which is being activated at specific time(surrounding that time).
The system should work once in a day.
I am setting value in a database which mention the activation time and every hour the system is pulling that value to check if the current time is matching the value (in case it is the system will activate itself).
This time has to be changeable in the future dynamiclly.
Now this technic gives me a headache, since I need to do some Math calculations (in case the current time has passed in couple of mins I still need to activate the system.
more over I need to take care for a case the system already activated so it wont be activated again in the same day (due to a time mistake caluclations.)
I could think about other technic which pulling the database once in couple of days to check if the activiation time has ever change(in this case I wont need to pull every hour, but in other case i am not sure Quartz can re-schedualre it's triggers while it's running)
any ideas? solutions?
Thanks,
ray.
You absolutely can reschedule triggers while Quartz is running (or add new triggers).
You can even do that from within the executing jobs if you like.
This a great example for my solution:
Dynamic time scheduling advice
I am building an app for which I need to set up cron jobs. What I want to do is to set the specific minutes in a hour where specific crons should run. For instance:
Task1 at 1st minute of the hour
Task2 on every second minute of the hour
Task3 every 2 minute only in the second half of the hour
Building this in the standard Unix cron format is reasonably straightforward, but could not figure out how to do it in the Google-App-Engine.
The documentation does not list any non-trivial examples. Any suggestions on how to do it? Examples would be excellent.
The documentation you linked to seems to indicate that it isn't possible to do what you want using only Cron for Java (unless they have an undocumented feature for it). In particular this doesn't appear to allow for multiple times.
time specifies the time of day, as HH:MM in 24 hour time.
The Python version says the exact same thing.
However, one solution (albeit somewhat more expensive in terms of CPU usage) would be to call a URL every minute, and from the handler for that URL, dispatch out to whatever other calls you need.
In other words, something like:
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/run-scheduled-tasks</url>
<description>Run all scheduled tasks</description>
<schedule>every 1 minutes</schedule>
</cron>
</cronentries>
Then in run-scheduled-tasks, check a database for when each task last run, and if your complex condition for triggering them has occurred since then.
If the documentation is correct you can't get as granular as you are wanting. Doesn't look like they support picking a particular minute of the hour. Or a subset of an hour.
You might have to get creative. Why do you need such specific timing?
This may seem silly. Write three servlet. And schedule them from another UNIX machine on the other part of the world :D. Or even you can write a java app to do it. enjoy
Have a look at Quartz and see if that'll solve your problem.