Обновление ежедневного счетчика даты с определенного времени
У меня есть две даты: "Дата начала 2018-01-01" и "Дата окончания 2018-01-31"
Я хочу сделать свою логику таким образом, чтобы каждый день моя начальная дата увеличивалась до достижения 2018-02-28. Ниже приведен фрагмент кода, который я пробовал. Как это можно исправить, так как Дата начала должна меняться ежедневно.
public class myclass {
public static void main(String a[]) {
try {
String dt = "2008-01-01"; // Start date
String dt1 = "2008-01-31"; // End date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
c.setTime(sdf.parse(dt));
c.add(Calendar.DATE, 1); // number of days to add
dt = sdf.format(c.getTime()); //
System.out.println(dt);
}catch (Exception ex) {
ex.printStackTrace();
}
}
}
PS: это выполнение в реальном времени, в планировщике, который работает ежедневно и проверяет дату окончания с заданной даты. Сколько дней осталось.
Спасибо
3 ответа
Runnable
Определите работу, которую вы должны сделать как Runnable
,
Тогда используйте Scheduled ExecutorService
запускать это каждую минуту или около того, сверяя текущую дату с целевой датой. Если обратный отсчет увеличился, обновите отображение в графическом интерфейсе. Если нет, ничего не делать, пусть Runnable
запустить снова через минуту.
Смотрите руководство Oracle по исполнителям.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); // Use a single thread, as we need this to run sequentially, not in parallel.
ses.scheduleWithFixedDelay( r , 0L , 1L , TimeUnit.MINUTES ); // Pass the `Runnable`, an initial delay, a count to wait between runs, and the unit of time for those two other number arguments.
Было бы более эффективно запланировать новый Runnable
каждый раз, вместо автоматического повторения, чтобы установить задержку рассчитанное количество времени до следующей полуночи. Таким образом, исполнитель будет спать весь день, а не бегать каждую минуту. Но такой подход может потерпеть неудачу, если часы пользователя обновляются до существенно отличающегося текущего времени или если текущий часовой пояс пользователя меняется (если вы используете настройку по умолчанию, а не устанавливаете ее явно). Учитывая, как мало это Runnable
Это необходимо сделать (просто проверьте текущую дату и рассчитайте оставшиеся дни), поэтому нет никаких практических причин не просто запускать ее каждую минуту или две (как бы ни была минимальна ваша терпимость к новому обновлению пользователя - бизнес-политика управления вашим приложением).
LocalDate
LocalDate
class представляет значение только для даты без времени суток и без часового пояса или смещения от UTC.
Часовой пояс имеет решающее значение при определении даты. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париже Франция - новый день, а в Монреале-Квебеке все еще "вчера".
Если часовой пояс не указан, JVM неявно применяет свой текущий часовой пояс по умолчанию. Это значение по умолчанию может измениться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться. Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента.
Укажите правильное название часового пояса в формате Continent/Region
, такие как America/Montreal
, Africa/Casablanca
, или же Pacific/Auckland
, Никогда не используйте 2-4 буквенное сокращение, такое как EST
или же IST
поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "Asia/Kolkata" ); // Or ZoneId.systemDefault() to rely on the JVM’s current default time zone.
LocalDate today = LocalDate.now( z );
пример
Вот полный пример. Для получения дополнительной информации, поиск переполнения стека. Использование ScheduledExecutorService
был покрыт уже много раз.
package work.basil.example;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class DailyCountdown implements Runnable {
private LocalDate dueDate;
private Long daysRemaining;
public DailyCountdown ( LocalDate dueDate ) {
this.dueDate = dueDate;
}
@Override
public void run () {
try {
System.out.println( "DEBUG - Running the DailyCountdown::run method at " + Instant.now() );
ZoneId z = ZoneId.of( "America/Montreal" ); // Or ZoneId.systemDefault() to rely on the JVM’s current default time zone.
LocalDate today = LocalDate.now( z );
Long count = ChronoUnit.DAYS.between( today , this.dueDate );
if ( Objects.isNull( this.daysRemaining ) ) {
this.daysRemaining = ( count - 1 );
}
if ( this.daysRemaining.equals( count ) ) {
// Do nothing.
} else {
// … Schedule on another thread for the GUI to update with the new number.
this.daysRemaining = count;
}
} catch ( Exception e ) {
// Log this unexpected exception, and notify sysadmin.
// Any uncaught exception reaching the scheduled executor service would have caused it to silently halt any further scheduling.
}
}
public static void main ( String[] args ) {
// Put this code where ever appropriate, when setting up your GUI after the app launches.
Runnable r = new DailyCountdown( LocalDate.of( 2018 , Month.FEBRUARY , 15 ) );
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleWithFixedDelay( r , 0L , 1L , TimeUnit.MINUTES );
// Be sure to gracefully shutdown the ScheduledExecutorService when your program is stopping. Otherwise, the executor may continue running indefinitely on the background thread.
try {
Thread.sleep( TimeUnit.MINUTES.toMillis( 7 ) ); // Sleep 7 minutes to let the background thread do its thing.
} catch ( InterruptedException e ) {
System.out.println( "The `main` thread was woken early from sleep." );
}
ses.shutdown();
System.out.println( "App is exiting at " + Instant.now() ) ;
}
}
API времени Java 8, вы можете легко достичь.
for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
...
}
Ты можешь использовать java.util.Timer
класс для этого.
В приведенной ниже программе я выбрал другой подход. Я НЕ использую дату начала. Я просто получаю текущую дату каждый день и сравниваю ее с контрольной датой (в данном примере это "2019-02-10"). Посмотрите, работает ли это по вашему требованию.
(Использование FIVE_SECONDS_IN_MILLISECONDS
протестировать программу.)
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class Scheduler {
private static final long ONE_DAY_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
private static final long FIVE_SECONDS_IN_MILLISECONDS = 1000 * 5;
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
Calendar c = Calendar.getInstance();
String dateString = sdf.format(c.getTime());
System.out.println(dateString);
if (dateString.equals("2019-02-10")) {
System.out.println("Date reached!");
}
}
};
Timer timer = new Timer();
timer.schedule(timerTask, 0, ONE_DAY_IN_MILLISECONDS/*FIVE_SECONDS_IN_MILLISECONDS*/);
}
}