【问题标题】:How to compare Two date in android?如何在android中比较两个日期?
【发布时间】:2016-06-25 22:12:30
【问题描述】:

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

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

【问题讨论】:

  • 为什么这被标记为重复,这个问题并没有解决我比较两种不同日期格式的担忧
  • downvoter 关心解释?
  • @tyczj 这是怎么复制的?
  • 是UTC的服务器日期时间,如果不是,您需要在解析之前设置服务器时间的时区
  • 这与讨论无关,但是您的代码中是否考虑了时区?例如。现在在东京是 3 月 11 日,06:26,而在洛杉矶是 3 月 10 日,13:26。如果您的代码忽略时区,您可能会出现不匹配

标签: android date datetime datetime-format


【解决方案1】:

我建议您使用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 了解有关 modern 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

【讨论】:

    【解决方案2】:

    借助DateFormat 类(例如SimpleDateFormat 类),您可以解析yyyy-mm-dd HH:mm:ss 日期。此操作将返回一个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...
    

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

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

    【讨论】:

    • 如何获取以毫秒为单位的时差来安排闹钟
    • 您可以致电parsed.getTime() 以获取以毫秒为单位的时间。在那之后,这只是一个数学问题..
    • 我试过 setExact 但不工作,你能发布一些在 alarmManager 中工作的代码
    • 您应该检查parsed 是否在未来(通过将其与System.currentTimeMillis() 进行比较)。如果是在未来,你想在那个时候触发警报,你应该使用parsed.getTime()作为alarmManager.setExact(...)方法的triggerAtMillis参数。
    • 我解决了,这只是一个 HH 问题,我是 HH,这就是为什么时间错了,既然你帮助了你,我接受了答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 2021-08-17
    • 2011-04-20
    • 1970-01-01
    相关资源
    最近更新 更多