从特定时间更新日期的每日计数器
Update Daily Counter Of Date From Specific Time
我有两个日期,说“2018-01-01”开始日期和“2018-01-31”结束日期
我想按照我的逻辑,每天我的开始日期都会增加,直到达到 2018 年 2 月 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 :此执行是实时的,在每天运行的调度程序中,并检查给定日期的结局日期。还有多少天。
谢谢
Java8的时间-API,你可以轻松实现。
for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
...
}
您可以使用 java.util.Timer
class。
在下面的程序中,我采用了不同的方法。我没有使用开始日期。我只是每天获取当前日期并将其与目标日期(在本例中为“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*/);
}
}
Runnable
将您需要完成的工作定义为 Runnable
。
然后每分钟左右使用 Scheduled ExecutorService
到 运行,对照目标日期检查当前日期。如果倒计时增加,则更新 GUI 中的显示。如果没有,什么也不做,让 Runnable
再过一分钟再 运行 。
参见Oracle Tutorial on Executors。
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
比自动重复更有效,这样可以将延迟设置为计算的时间量,直到下一个午夜。这样执行者就会睡一整天而不是每分钟 运行ning。但是,如果用户的时钟更新到一个明显不同的当前时间,或者如果用户当前的默认时区发生变化(如果您依赖于默认值而不是明确设置时区),那么这种方法可能会失控。考虑到这个 Runnable
需要做的事情很少(只需检查当前日期和计算剩余天数),没有任何实际理由不让它 运行 每分钟或每两分钟(但是您对新更新的最小容忍度是多少给用户 - 您的应用程序管理的业务策略)。
LocalDate
LocalDate
class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
时区对于确定日期至关重要。对于任何给定时刻,日期在全球范围内因地区而异。例如,Paris France is a new day while still “yesterday” in Montréal Québec.
午夜后几分钟
如果未指定时区,JVM 将隐式应用其当前默认时区。该默认值在 运行 时间 (!) 期间可能 change at any moment,因此您的结果可能会有所不同。最好明确指定您的 desired/expected 时区作为参数。
以Continent/Region
的格式指定一个proper time zone name,例如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 );
例子
这是完整的例子。有关更多信息,请搜索 Stack Overflow。 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() ) ;
}
}
我有两个日期,说“2018-01-01”开始日期和“2018-01-31”结束日期
我想按照我的逻辑,每天我的开始日期都会增加,直到达到 2018 年 2 月 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 :此执行是实时的,在每天运行的调度程序中,并检查给定日期的结局日期。还有多少天。
谢谢
Java8的时间-API,你可以轻松实现。
for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
...
}
您可以使用 java.util.Timer
class。
在下面的程序中,我采用了不同的方法。我没有使用开始日期。我只是每天获取当前日期并将其与目标日期(在本例中为“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*/);
}
}
Runnable
将您需要完成的工作定义为 Runnable
。
然后每分钟左右使用 Scheduled ExecutorService
到 运行,对照目标日期检查当前日期。如果倒计时增加,则更新 GUI 中的显示。如果没有,什么也不做,让 Runnable
再过一分钟再 运行 。
参见Oracle Tutorial on Executors。
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
比自动重复更有效,这样可以将延迟设置为计算的时间量,直到下一个午夜。这样执行者就会睡一整天而不是每分钟 运行ning。但是,如果用户的时钟更新到一个明显不同的当前时间,或者如果用户当前的默认时区发生变化(如果您依赖于默认值而不是明确设置时区),那么这种方法可能会失控。考虑到这个 Runnable
需要做的事情很少(只需检查当前日期和计算剩余天数),没有任何实际理由不让它 运行 每分钟或每两分钟(但是您对新更新的最小容忍度是多少给用户 - 您的应用程序管理的业务策略)。
LocalDate
LocalDate
class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
时区对于确定日期至关重要。对于任何给定时刻,日期在全球范围内因地区而异。例如,Paris France is a new day while still “yesterday” in Montréal Québec.
午夜后几分钟如果未指定时区,JVM 将隐式应用其当前默认时区。该默认值在 运行 时间 (!) 期间可能 change at any moment,因此您的结果可能会有所不同。最好明确指定您的 desired/expected 时区作为参数。
以Continent/Region
的格式指定一个proper time zone name,例如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 );
例子
这是完整的例子。有关更多信息,请搜索 Stack Overflow。 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() ) ;
}
}