计算当前时间和某一天之间的时间

时间:2014-03-07 18:08:08

标签: java android date time calendar

我是(Java)编程的新手,我正在尝试构建一个小的Android应用程序,告诉你它是否已经是周末。

到目前为止我已经知道它可以告诉你它是否是周末,但是我也希望在该应用程序中显示一个小倒计时器,直到周末开始或结束。

我无法考虑算法来计算当前时间与下周六(如果不是周末)或周一(如果是周末)之间的时间(以毫秒为单位)。

我知道如何使用Calendar课程获得当周的当天,但是当我尝试将时间推迟到下周六或周一时,我会陷入困境。我想不出办法做到这一点。

这可能听起来像一个愚蠢的问题,但我真的在这里失去了理智。希望你们其中一个人可以帮助我。

2 个答案:

答案 0 :(得分:4)

这是一个过程,但作为描述而不是代码,剩下的作为实现练习:

  • 以毫秒为单位获取当前时间,并记住以后
  • 创建适当的Calendar对象
  • 找出你想要瞄准的那一天(周六或周一)
  • 计算你需要添加多少天才能到达那里(基于当前的“星期几”和你想要的星期几),并添加这么多天
    • 作为一种更简单(但效率更低)的选择:继续增加1天,直到星期几为止!
  • 使用多个set调用来获取正确的时间(因此将小时设置为0,将分钟设置为0,将秒设置为0,将毫秒设置为0) - 假设您正在寻找午夜,当然
  • 使用getTimeInMillis()获取您的目标时间
  • 减去原始值,结果将是您需要等待的毫秒数

要记住的一点是,夏令时变化会让事情变得“有趣”......所以在星期六开始时,可能在你到达之前的47或49小时周一的开始,而不是正常的48.我希望上面的算法在大多数情况下能够应对,但如果你“瞄准”星期天你可能会在巴西(以及其他一些地方)遇到奇怪的情况到了午夜,因为这可能会被完全跳过......时区很烦人。

此外,如果你可以使用Joda Time,它可以让你的生活更简单。

答案 1 :(得分:1)

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

另外,下面引用的是来自 home page of Joda-Time 的通知:

<块引用>

请注意,从 Java SE 8 开始,要求用户迁移到 java.time (JSR-310) - JDK 的核心部分,取代了该项目。

使用 java.time(现代日期时间 API)的解决方案:

该解决方案使用以下函数:

  1. ZonedDateTime#now(ZoneId):从指定时区的系统时钟返回当前日期时间。
  2. ZonedDateTime#getDayOfWeek:返回星期字段,它是一个枚举 DayOfWeek
  3. TemporalAdjusters#next:返回下一个星期调整器,它将日期调整到被调整的日期之后指定星期几的第一次出现。
  4. ZonedDateTime#toLocalDate:返回此日期时间的 LocalDate 部分。
  5. LocalTime#atStartOfDay(ZoneId):根据时区中的规则返回从该日期开始的最早有效时间的分区日期时间。
  6. ChronoUnit#between:计算两个时间对象之间的时间量。

演示:

import static java.time.DayOfWeek.SATURDAY;
import static java.time.DayOfWeek.SUNDAY;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.TextStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Tests
        process(ZonedDateTime.now(ZoneId.systemDefault()));
        process(ZonedDateTime.of(LocalDate.of(2021, 6, 23), LocalTime.of(10, 20, 30, 123456789),
                ZoneId.systemDefault()));
        process(ZonedDateTime.of(LocalDate.of(2021, 6, 26), LocalTime.of(10, 20, 30, 123456789),
                ZoneId.systemDefault()));
    }

    static long millisBetween(ZonedDateTime start, ZonedDateTime end) {
        return ChronoUnit.MILLIS.between(start, end);
    }

    static boolean isWeekend(ZonedDateTime now) {
        DayOfWeek dow = now.getDayOfWeek();
        return dow == SATURDAY || dow == SUNDAY;
    }

    static void process(ZonedDateTime now) {
        String dow = now.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH);
        if (isWeekend(now)) {
            System.out.printf("It's %s (a weekend) now. Monday is %d milliseconds ahead.%n", dow,
                    millisBetween(now, now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).toLocalDate()
                            .atStartOfDay(ZoneId.systemDefault())));
        } else {
            System.out.printf("It's %s (a weekday) now. Saturday is %d milliseconds ahead.%n", dow,
                    millisBetween(now, now.with(TemporalAdjusters.next(DayOfWeek.SATURDAY)).toLocalDate()
                            .atStartOfDay(ZoneId.systemDefault())));
        }
    }
}

样本运行的输出:

It's Sunday (a weekend) now. Monday is 30258373 milliseconds ahead.
It's Wednesday (a weekday) now. Saturday is 221969876 milliseconds ahead.
It's Saturday (a weekend) now. Monday is 135569876 milliseconds ahead.

ONLINE DEMO

注意:要使代码适用于不同于 JVM 时区的时区,请将 ZoneId.systemDefault() 替换为适用的时区 ID,例如ZoneId.of("America/New_York")

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project