【问题标题】:date and time show parse error at specific index日期和时间在特定索引处显示解析错误
【发布时间】:2021-03-06 05:53:25
【问题描述】:

我从 JSON API URL 获取日期和时间,格式如下

    '2021-03-05 09:18:07' which is in String form.

但是当我想以毫秒为单位进行转换时,它给了我一个索引 10 的错误。我不知道为什么会出现这个问题,我检查了其他 Stackoverflow 答案但没有成功

  DateTimeFormatter formatter ;
                                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                                    formatter = DateTimeFormatter.ofPattern(
                                            "yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT);
                                    String dates = object.getString("created_at");
                                   long  timeInMilliseconds = OffsetDateTime.parse(dates, formatter)
                                            .toInstant()
                                            .toEpochMilli();
                                    System.out.println("Date in milli :: USING ThreeTenABP >>> " + 
                                   timeInMilliseconds);

                                }
                                String text = TimeAgo.using(timeInMilliseconds);
                                FeedModel.setDateSnap(text);

这是错误

     java.time.format.DateTimeParseException: Text '2021-03-05 09:18:07' could not be parsed: Unable 
     to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2021-03-05T09:18:07 of type 
     java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
    at java.time.OffsetDateTime.parse(OffsetDateTime.java:396)
    at com.example.wasigram.MainActivity$1.onResponse(MainActivity.java:91)
    at com.androidnetworking.common.ANRequest.deliverSuccessResponse(ANRequest.java:729)
    at com.androidnetworking.common.ANRequest.access$6500(ANRequest.java:80)
    at com.androidnetworking.common.ANRequest$6.run(ANRequest.java:709)
    at android.os.Handler.handleCallback(Handler.java:888)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:213)
    at android.app.ActivityThread.main(ActivityThread.java:8178)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
 Caused by: java.time.DateTimeException: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2021-03-05T09:18:07 of type java.time.format.Parsed
    

【问题讨论】:

    标签: java android datetime datetime-parsing datetimeparseexception


    【解决方案1】:

    使用Java SE 8 API:

    您可以使用DateTimeFormatter#withZone 获取具有指定区域的格式化程序。

    另外,使用正确的格式,yyyy-MM-dd HH:mm:ss,它没有 'T',你错误地放入了你的模式。事实上,我更喜欢使用u 而不是y,如this answer 中所述。

    演示:

    import java.time.OffsetDateTime;
    import java.time.ZoneOffset;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String strDateTime = "2021-03-05 09:18:07";
            
            DateTimeFormatter formatter = DateTimeFormatter
                                            .ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH)
                                            .withZone(ZoneOffset.UTC);
            
            long millis = OffsetDateTime
                            .parse(strDateTime, formatter)
                            .toInstant()
                            .toEpochMilli();
            
            System.out.println(millis);
        }
    }
    

    输出:

    1614935887000
    

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。

    使用ThreeTen-Backport API

    import java.util.Locale;
    
    import org.threeten.bp.LocalDateTime;
    import org.threeten.bp.ZoneOffset;
    import org.threeten.bp.format.DateTimeFormatter;
    
    public class Main {
        public static void main(String[] args) {
            String strDateTime = "2021-03-05 09:18:07";
            
            DateTimeFormatter formatter = DateTimeFormatter
                                            .ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
            
            long millis = LocalDateTime
                            .parse(strDateTime, formatter)
                            .toInstant(ZoneOffset.UTC)
                            .toEpochMilli();
            
            System.out.println(millis);
        }
    }
    

    输出:

    1614935887000
    

    【讨论】:

      【解决方案2】:

      你有两个问题:

      1. 您的格式模式字符串与 JSON 中的字符串不完全匹配。
      2. 您不能天真地将不包含 UTC 偏移量的搅拌解析为 OffsetDateTime

      格式模式字符串

      您的字符串2021-03-05 09:18:07 中的索引10 是月份之后的空格所在的位置。因此,让我们看看您的格式模式,看看一个月之后的预期是什么。你的格式模式字符串是yyyy-MM-dd'T'HH:mm:ss,在月份之后是'T',这意味着文字T,即T不是模式字母。你的例外是因为 T 和空格不相等。

      解析问题提示:当你看不出解析有什么问题时,先尝试格式化。

          String dates = "2021-03-05 09:18:07";
          DateTimeFormatter formatter 
                  = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT);
          
          OffsetDateTime expectedResult
                  = OffsetDateTime.of(2021, 3, 5, 9, 18, 7, 0, ZoneOffset.ofHours(1));
          
          System.out.println("Parsing:   " + dates);
          System.out.println("Formatted: " + expectedResult.format(formatter));
      

      输出是:

      Parsing:   2021-03-05 09:18:07
      Formatted: 2021-03-05T09:18:07
      

      我希望现在可以更轻松地查看字符串中的空格与格式化程序期望的字符串中的T 之间的区别。

      您可能已经想出了解决方案:在格式模式字符串中放置一个空格而不是 'T'(如果您愿意,可以将空格放在单引号中,但这不是必需的)。

      解析成 OffsetDateTime

      此修复仍然失败:

          // Put a space in the format pattern string
          DateTimeFormatter formatter 
                  = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
          
          OffsetDateTime odt = OffsetDateTime.parse(dates, formatter);
      

      线程“主”java.time.format.DateTimeParseException 中的异常: 无法解析文本“2021-03-05 09:18:07”:无法获取 来自 TemporalAccessor: {} 的 OffsetDateTime,ISO 解析为 java.time.format.Parsed 类型的 2021-03-05T09:18:07

      有趣的是,这也是您问题的堆栈跟踪中的异常。

      OffsetDateTime 必须包含与 UTC 的偏移量,而 Java 无处可取。您知道您从哪个时区获取字符串的 API 假定了哪个时区?如果是这样,请使用它。我的建议是:

          ZoneId zoneAssumedByApi = ZoneId.of("Antarctica/Troll");
          long  timeInMilliseconds = LocalDateTime.parse(dates, formatter)
                  .atZone(zoneAssumedByApi)
                  .toInstant()
                  .toEpochMilli();
          System.out.println("Date in milli :: USING ThreeTenABP >>> "
                  + timeInMilliseconds);
      

      以毫秒为单位的日期 :: 使用 ThreeTenABP >>> 1614935887000

      【讨论】:

      • 我已经从服务器获得,我会在我的回答中向您展示,那么在没有 UTC 的情况下我能做什么
      • 好吧,对不起,如果您不知道服务器使用的是 Pacific/Auckland、UTC 还是 Pacific/Pago_Pago 时区,那么您无法将日期和时间转换为自纪元以来的毫秒数。 2021-03-05 09:18:07 的时间跨度约为 24 或 26 小时,具体取决于它所在的时区。
      • atzone 显示错误但 atZoneSimilarLocal 和 atZoneSameInstant 选择哪一个?
      • 通常atZoneSameInstant(),但这取决于上下文和要求。你记得LocalDateTime.parse而不是OffsetDateTime吗?
      猜你喜欢
      • 1970-01-01
      • 2018-05-27
      • 1970-01-01
      • 2017-06-29
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-28
      相关资源
      最近更新 更多