我的服务器日期格式为yyyy-mm-dd HH:mm:ss
。我的当前时间为毫秒System.currentTimeMillis()
。我想比较两个日期,看看从服务器收到的日期是否是未来日期,如果是,那么为未来日期安排警报。
所以我的问题是如何比较这2种不同的格式日期以及如何获得剩余时间(未来 - 当前)以便安排警报。
编辑:
我已经尝试用millis解析日期,但它不会返回与System.currentTimeMillis()
格式相同的值。所以它失败了
答案 0 :(得分:4)
您可以通过yyyy-mm-dd HH:mm:ss
课程(例如SimpleDateFormat课程)解析DateFormat
日期。此操作将返回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(...)
之间执行的代码{{1}}。
答案 1 :(得分:2)
我建议您使用 modern date-time API*。
使用现代 API 执行此操作的一种简单方法是使用服务器的时区将服务器的日期时间字符串解析为 ZonedDateTime
,并将结果对象转换为 Instant
,您可以将其与 {{ 1}}。
演示:
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.");
}
}
从 modern date-time API 中了解有关 Trail: Date Time* 的更多信息。
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。