【问题标题】:Unexpected side effects when parsing dates in Android在 Android 中解析日期时出现意外的副作用
【发布时间】:2012-12-27 21:23:24
【问题描述】:

在各种Android项目中,我使用下面的静态函数来解析1900-12-31等日期。当然,这个函数应该是确定性的——但事实证明不是。为什么?

通常,它会将日期 2010-10-30 解析为正确的 Date 实例来保存该值。但是我注意到,当我同时运行一个IntentService 并解析一些日期时,此函数会将与上面相同的日期解析为1983-01-20,这是IntentService 中解析的日期之一。怎么会这样?

public static Date dateFromString(String dateStr) {
    SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    SimpleDateFormat mDateTimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());
    Date dateOut = null;
    try {
        if (dateStr != null) {
            if (dateStr.length() == 7) {
                if (dateStr.startsWith("--")) {
                    dateStr = "0000"+dateStr.substring(1);
                }
            }
            else if (dateStr.length() == 6) {
                if (dateStr.startsWith("-")) {
                    dateStr = "0000"+dateStr;
                }
            }
            else if (dateStr.length() == 5) {
                dateStr = "0000-"+dateStr;
            }
            else if (dateStr.matches("[0-9]{2}\\.[0-9]{2}\\.[0-9]{4}")) {
                dateStr = dateStr.substring(6, 10)+"-"+dateStr.substring(3, 5)+"-"+dateStr.substring(0, 2);
            }
            else if (dateStr.matches("[0-9]{2}\\/[0-9]{2}\\/[0-9]{4}")) {
                dateStr = dateStr.substring(6, 10)+"-"+dateStr.substring(3, 5)+"-"+dateStr.substring(0, 2);
            }
            else if (dateStr.matches("[0-9]{8}")) {
                dateStr = dateStr.substring(0, 4)+"-"+dateStr.substring(4, 6)+"-"+dateStr.substring(6, 8);
            }
            if (dateStr.length() >= 20) {
                String dateTimeStr = dateStr.trim();
                if (dateTimeStr.endsWith("Z")) {
                    dateTimeStr = dateStr.substring(0, dateTimeStr.length()-1)+"+0000";
                }
                if (dateStr.charAt(10) == ' ') {
                    dateTimeStr = dateStr.substring(0, 10)+"T"+dateStr.substring(11);
                }
                try {
                    dateOut = mDateTimeFormat.parse(dateTimeStr);
                }
                catch (Exception e2) {
                    dateOut = mDateFormat.parse(dateStr);
                }
            }
            else {
                dateOut = mDateFormat.parse(dateStr);
            }
        }
    }
    catch (Exception e) {
        dateOut = null;
    }
    return dateOut;
}

编辑:我在我的ActivityonCreate() 中进行解析,在那里我启动了一个完成这项工作的AsyncTask。在ActivityonStop() 中,启动了执行相同工作的后台服务。当我关闭应用程序 (onStop()) 并快速重新启动它 (onCreate()) 时,两者似乎同时运行并且发生错误。

【问题讨论】:

  • 作为一个实验,如果你让dateFromString同步会发生什么?
  • 首先,为什么是static这个方法,其次是哪个类?
  • @DiegoBasch 谢谢,我会努力的!但实际上,synchronized 绝不应该是必要的,因为它只能防止对对象的干扰——这里没有使用(静态)。
  • @Squonk 实际上,它以前是非静态的。但由于它不对任何对象进行操作,所以我将其设为静态。非静态方法也出现了问题。它位于MyApp.java,延伸至Application
  • @MarcoW。 :我认为 Dheeraj V.S. 的答案。可能解释它。 SimpleDateFormat 不是线程安全的事实很可能是问题的原因。

标签: android android-date


【解决方案1】:

SimpleDateFormat 的文档说:

SimpleDateFormat 不是线程安全的。用户应该创建一个单独的 每个线程的实例。

给你。只需在每个线程中分别创建SimpleDateFormat 对象并将其传递给方法即可。

【讨论】:

  • 他确实在每个线程中创建了一个单独的实例,实际上他在每次调用中创建了两个新实例。
  • 谢谢!我没想到parse() 方法会产生副作用并更改类的某些字段——但实际上parse() 方法(继承自Date 类)写入Date 的字段@ 987654328@。因此,同时使用parse() 会导致问题是合乎逻辑的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 2021-03-21
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
相关资源
最近更新 更多