java - 从特定时间更新日期的每日计数器

标签 java date java-calendar

我有两个日期,分别是“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:此执行是实时的,在每天运行的调度程序中,并检查给定日期的结束日期。还有多少天。

谢谢

最佳答案

可运行

将您需要完成的工作定义为 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 比自动重复更有效,这样可以将延迟设置为计算的时间量,直到下一个午夜。这样执行者就可以睡一整天而不是每分钟都在运行。但是,如果用户的时钟更新到一个明显不同的当前时间,或者如果用户当前的默认时区发生变化(如果您依赖于默认值而不是明确设置时区),那么这种方法可能会失控。考虑到这个 Runnable 需要做的事情很少(只需检查当前日期和计算剩余天数),没有任何实际理由不让它每隔一两分钟运行一次(无论您对新更新的最小容忍度是多少)用户 - 您的应用程序管理的业务策略)。

本地日期

LocalDate类表示没有日期时间且没有 time zone 的纯日期值或 offset-from-UTC .

时区对于确定日期至关重要。对于任何给定时刻,日期在全局范围内因地区而异。例如,午夜后几分钟 Paris France是新的一天,但在Montréal Québec 中仍然是“昨天” .

如果未指定时区,JVM 将隐式应用其当前默认时区。该默认值可能 change at any moment在运行时 (!),因此您的结果可能会有所不同。最好将您想要/期望的时区明确指定为参数。

指定 proper time zone name格式为Continent/Region,例如America/MontrealAfrica/Cas​​ablancaPacific/Auckland .切勿使用 2-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。

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() ) ;
    }
}

关于java - 从特定时间更新日期的每日计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54389391/

相关文章:

java - 使用 reduce(3 个参数)函数传递集合 - 流 java 8

javascript - 使用 jquery 格式化和打印日期

php - PHP 中的 Cookie 过期日期(在自定义日期)

Java如何从给定时间字符串中删除第n分钟而不考虑时区

java - 在Java中获取带有国家代码的地区的时区

java - 在 Java 中检查其他两个日期之间的日期时得到不正确的结果

java - 如何让 Jackson 序列化器更加 DRY?

java - "This advice advises no methods"与 AspectJ

Java HashMap<String, ArrayList<Object[]>>如何添加一个空数组?

ruby-on-rails - RoR - collection_select 从数组