与时区无关的日期/时间

时间:2012-09-26 19:00:29

标签: java android jodatime

我要做的是Android上的基本闹钟应用。当我通过UI设置日期和时间时(比如2012-09-26 14:37),我希望当时的闹钟响起,不管时区如何。该设置被序列化为两个单独的值 - 日期值和从一天开始的偏移量(以毫秒为单位)。

我也错误地使用Joda库进行日期/时间操作。 API看起来非常类似于.NETs DateTime API,但是仍然遇到与默认Java框架API相同的二元性问题,其中对象值是UTC,但它的属性是在本地时间(这个概念让我大吃一惊btw) )。它似乎也无法自动获取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
    }
}

在应用程序运行时(设置完成后)我尝试切换时区时,一切都很好,很花哨。这是奇怪的东西开始的地方。我甚至无法描述究竟出了什么问题,除此之外无论我做什么都不行。

我想我正在寻找的是关于如何在Joda或标准API中使用Java / Android进行时区独立数学的一般方向。

2 个答案:

答案 0 :(得分:2)

我使用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(...)方法会创建一个警报,该警报将在任何时区的确切时间触发。

要执行您所描述的内容,我会将上述代码与监听BroadcastReceiver的{​​{1}}结合使用 - 将其在清单中注册为ACTION_TIMEZONE_CHANGED

android.intent.action.TIMEZONE_CHANGED中我会调用上面显示的方法,该方法应该(理论上)取消之前的警报,并在时区更改时为当地时间设置一个新警报。 / p>

答案 1 :(得分:0)

事实证明,Jodatime不会处理Android上的时区变化。重新启动应用程序会有所帮助,但该解决方案不适用于始终运行的后台服务。我最终使用Calendar / Date API重写代码,即使它很难看也很痛苦。