【问题标题】:timezone-independent date/time与时区无关的日期/时间
【发布时间】:2012-09-26 19:00:28
【问题描述】:

我正在尝试做的是 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 进行与时区无关的数学运算的一般方向。

【问题讨论】:

  • 我不明白你在寻找什么,因为没有时区独立时间这样的东西。如果您将闹钟设置为美国东部时间晚上 8 点(格林威治标准时间 - 5 点),您希望闹钟在美国东部夏令时间晚上 7 点(格林威治标准时间 - 6 点)还是晚上 8 点响起?
  • 那么就没有数学了。将闹钟时间保存为一对整数(小时 0 - 23,分钟 0 - 59),并将整数转换为本地时区的时间以进行闹钟检查。
  • @GilbertLeBlanc 显然不能解决任何问题。时间日期反序列化后发生此问题。
  • 变量日期是您序列化/反序列化的那个吗?而对你来说,它是作为一个 Date 对象吗?这可能是问题所在,因为日期将保持其时区,而与之相比的新日期将在另一个时区。

标签: java android jodatime


【解决方案1】:

我使用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_CHANGEDBroadcastReceiver 结合起来 - 在清单中将其注册为 android.intent.action.TIMEZONE_CHANGED

BroadcastReceiver 中,我会让它调用我上面显示的方法,该方法应该(理论上)取消上一个警报并在时区更改时为当地时间设置一个新警报。

【讨论】:

  • 感谢您的帮助。尽管在这种情况下它并没有直接帮助我,但我不知道AlarmManager,这是我下次应该使用的东西。
【解决方案2】:

事实证明,Jodatime 不处理 Android 上的时区更改。重新启动应用程序会有所帮助,但该解决方案不适用于一直运行的后台服务。我最终使用 Calendar/Date API 重写了代码,尽管它丑陋而痛苦。

【讨论】:

    猜你喜欢
    • 2021-06-04
    • 2015-03-06
    • 2021-05-20
    • 1970-01-01
    • 2019-07-18
    • 2022-01-25
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多