如何比较 android 中的两个日期?

How to compare Two date in android?

我有一个格式为 yyyy-mm-dd HH:mm:ss 的服务器日期。我有 System.currentTimeMillis() 以毫秒为单位的当前时间。我想比较这两个日期,看看从服务器收到的日期是否是未来的日期,如果是这样,则为未来的日期安排一个警报。 所以我的问题是如何比较这 2 个不同格式的日期以及如何获取剩余时间(未来-当前)以便安排警报。

编辑: 我已经尝试以毫秒为单位解析日期,但它的 return 值与 System.currentTimeMillis() 的格式不同。所以它失败了

由于 DateFormat class(例如 SimpleDateFormat class),您可以解析 yyyy-mm-dd HH:mm:ss 日期。此操作将 return 一个 Date 对象。

您还可以从当前时间(以毫秒为单位)创建 Date 对象。

当您拥有两个对象时,您可以使用 compareTo 方法比较它们。

例如下面的代码:

try {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date parsed = sdf.parse("2016-03-10 22:05:20");

    Date now = new Date(System.currentTimeMillis()); // 2016-03-10 22:06:10

    System.out.println(parsed.compareTo(now));
} catch (Exception e) {
    e.printStackTrace();
}

将打印-1,这意味着parsed之前 now.

编辑:

这是一个使用 AlarmManager 的简单但无用的应用程序的代码。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Log.d("TAG", "From intent: "+getIntent().getStringExtra("MyEXTRA"));
}

@Override
protected void onResume() {
    super.onResume();

    try {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long parsedMillis = sdf.parse("2016-03-10 22:54:30").getTime();
        long now = System.currentTimeMillis(); // 22:54:15

        if (parsedMillis > now) {
            Log.d("TAG", "In the future!");

            AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
            Intent intent = new Intent(this, MyActivity.class);
            intent.putExtra("MyEXTRA", "From alarm");
            PendingIntent broadcast = PendingIntent.getActivity(this, 0, intent, 0);
            am.setExact(AlarmManager.RTC_WAKEUP, parsedMillis, broadcast);

        } else {
            Log.d("TAG", "In the past...");
        }


    } catch (Exception e) {
        e.printStackTrace();
    }
}

在 LogCat 你会看到:

03-10 22:54:20.925    3946-3946/com.example.myapp D/TAG﹕ From intent: null
03-10 22:54:21.227    3946-3946/com.example.myapp D/TAG﹕ In the future!
03-10 22:54:30.513    3946-3946/com.example.myapp D/TAG﹕ From intent: From alarm
03-10 22:54:30.577    3946-3946/com.example.myapp D/TAG﹕ In the past...

打印最后一行是因为警报导致 activity 重新启动,因此 onResume 将被再次调用并且 System.currentTimeMillis() 将大于硬编码时间。但是,如您所见,警报已在预定时间正确触发。

此外,您应该考虑边缘情况:如果 parsedMillis 仅比 now 大几毫秒,您可以设置永远不会触发的警报,因为它是过去设置的。发生这种情况是因为 OS 需要一些时间来执行您的代码,因此您应该检查 parsedMillis > now + DELTA,其中 DELTA 是一个合理的时间量,它取决于您在 [=] 之间执行的代码22=] 和 am.setExact(...).

我建议您使用 modern date-time API*.

使用现代 API 的一种简单方法是使用服务器的时区将服务器的日期时间字符串解析为 ZonedDateTime 并将结果对象转换为 Instant您可以与 Instant#now.

进行比较

演示:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // An arbitrary date for demo
        String strDateTime = "2021-05-09 10:20:30";

        // Replace JVM's default time zone, ZoneId.systemDefault() with applicable time
        // zone e.g. ZoneId.of("America/New_York")
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
                                    .withZone(ZoneId.systemDefault());

        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);

        Instant instantServer = zdt.toInstant();
        Instant now = Instant.now();

        if (instantServer.isBefore(now))
            System.out.println("The server time is before the current time.");
        else if (instantServer.isAfter(now))
            System.out.println("The server time is after the current time.");
        else
            System.out.println("The server time is the same as the current time.");
    }
}

当我 运行 它现在在我的系统中时输出:

The server time is before the current time.

Trail: Date Time[=40= 中了解有关 modern date-time API* 的更多信息].


* 无论出于何种原因,如果您必须坚持Java 6 或Java 7,您可以使用ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and