我想做的是 Android 上的一个基本闹钟应用程序。当我通过 UI 设置日期和时间(例如 2012 年 9 月 26 日 14:37)时,我希望闹钟在那时响起,无论时区如何。该设置被序列化为两个单独的值 - 日期值和距当天开始的偏移量(以毫秒为单位)。
我还犯了一个错误,即使用 Joda 库进行日期/时间操作。该 API 看起来与 .NET 的 DateTime API 非常相似,但仍然受到与默认 Java 框架 API 相同的二元性问题的困扰,其中对象值采用 UTC,但其属性采用本地时间(顺便说一句,这个概念让我大吃一惊) )。它似乎也无法自动获取 Android 的时区更改。
这是我所拥有的内容的摘要:
// part of reminder class
public DateTime getNextAlarm()
{
DateTime now = DateTime.now();
DateTime next = date.withMillisOfDay(time);
while (next.compareTo(now) <= 0)
next = next.plusDays(repeat);
return next;
}
// inside worker thread
workerEnabled = true;
while (workerEnabled)
{
try
{
Thread.sleep(10000);
}
catch (InterruptedException e)
{
workerEnabled = false;
return;
}
DateTimeZone tz = DateTimeZone.forTimeZone(TimeZone.getDefault());
if (nextAlarm != null && nextAlarm.withZoneRetainFields(tz).compareTo(new DateTime(tz)) < 0)
{
nextAlarm = reminder.getNextAlarm();
// perform alarm action
}
}
一切都很好,直到我尝试在应用程序运行时切换时区(设置完成后)。这就是奇怪的事情开始的地方。我什至无法描述到底出了什么问题,除了无论我做什么都无法正常工作。
我想我正在寻找的是关于如何在 Java/Android 中在 Joda 或标准 API 中进行与时区无关的数学计算的一般方向。
最佳答案
我使用 AlarmManager
在一天中的特定时间下载文件。我有一个辅助类的示例代码...
public void createDownloadAlarm() {
Intent i = new Intent(MyApp.ACTION_DOWNLOAD_FILES);
PendingIntent operation = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 1);
cal.set(Calendar.MINUTE, 30);
cal.set(Calendar.SECOND, 0);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, operation);
}
使用Calendar.getInstance()
,然后使用set(...)
方法创建一个闹钟,该闹钟将在任何时区的确切时间触发。
为了执行您所描述的操作,我会将上述代码与监听 ACTION_TIMEZONE_CHANGED
的 BroadcastReceiver
结合起来 - 将其在 list 中注册为 android.intent。 action.TIMEZONE_CHANGED
。
在BroadcastReceiver
中,我会让它调用上面显示的方法,该方法(理论上)应该取消上一个警报,并在时区改变时为本地时间设置一个新的警报变化。
关于java - 与时区无关的日期/时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12608593/