Executor
Old-school way used the Timer
class.
New-school way uses the Executors framework that handle the nitty-gritty details of scheduling tasks on background threads.
Set up an executor to run a Runnable
every few hours. That task checks the current moment. If the day-of-week of the current date is a Monday, and if your file is not yet written, write it. If not, then let the Runnable expire. The scheduled executor service will run again in a few hours, and repeat again and again.
The first step is to get the current date.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 2-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z );
from that get the current day of the week.
DayOfWeek dow = today.getDayOfWeek() ;
If today is a Monday, then see if file has yet been written. If not, write it.
if( dow.equals( DayOfWeek.MONDAY ) ) {
if( file not written ) { write file }
}
Put that all together into a named method.
private void writeFileOnMonday ( ) {
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
DayOfWeek dow = today.getDayOfWeek();
if ( dow.equals( DayOfWeek.MONDAY ) ) {
if ( file not written ){ write file }
}
}
Harness that workload in a scheduled executor service. Specify how many hours to wait between runs. If we specify to run our task every 3 hours, then, logic dictates, our weekly file will be written sometime between midnight and 3 AM on each Monday.
One big catch with a scheduled executor service: The repeating task execution comes silently to a halt if on any run a Throwable
(Exception
or Error
) is thrown by your task, and reaches the executor. So always wrap your task in a try-catch. See this Question.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); // Convenience method to produce an executor service.
ScheduledFuture scheduledFuture = // A handle to check the status of your task. May or may not be useful to you.
scheduledExecutorService
.scheduleWithFixedDelay( new Runnable() { // Implement the `Runnable` interface as your task.
@Override
public void run ( ) {
try {
writeFileOnMonday();
} catch (Exception e ) {
… handle unexected exception
}
}
} ,
0 , // Initial delay
3 , // Delay between runs.
TimeUnit.HOURS ); // Unit of time meant for the pair of delay numbers above.
Search Stack Overflow for more info, as all this has been covered many many times already.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.