如何比较 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 。
我有一个格式为 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