【问题标题】:Getting wrong date when I am trying to parse actual date当我试图解析实际日期时得到错误的日期
【发布时间】:2017-11-12 04:45:43
【问题描述】:

我的实际日期格式是:

6 月 10 日星期六上午 11:18

我想将此格式转换为yyyy-MM-dd HH:mm:ss

为此,我正在尝试使用以下代码解析输入字符串:

SimpleDateFormat format = new SimpleDateFormat("EEEE, MMMM dd HH:mm aa", Locale.ENGLISH);
Log.d("date:","date is:"+format.parse(resultstr));

该行的输出给出:

1970 年 6 月 10 日星期三 00:00:00 GMT+05:30

但我不知道为什么它给出的是这个值而不是实际值。

【问题讨论】:

  • 你不给它一年,它怎么会知道年份?事实上,根据您当前的代码,不可能知道您要查找的年份。
  • 我可以看到的一个问题是您的格式化程序无法知道您的日期在哪一年,因此工作日与日/月的匹配将是一个问题
  • 6 月 10 日星期六每 7 年仅存在一次(闰年或闰年)
  • @cricket_007 实际上,您可以确实“看到一年后”——将输入解析为MonthDay sans year。见my Answer below

标签: java android date datetime datetime-parsing


【解决方案1】:

java.time.MonthDay

您可以将日期部分解析为MonthDay 对象,将时间部分解析为LocalTime

我没有尝试过这段代码,但它可能会起作用。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEEE, MMMM dd HH:mm a" , Locale.US ) ;
String input = "Saturday, June 10 11:18 AM" ;
MonthDay md = MonthDay.parse( input , f ) ;
LocalTime lt = LocalTime.parse( input , f ) ;

指定获取LocalDate的年份。

LocalDate ld = md.atYear( 2017 );

指定用作此日期时间上下文的时区。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

【讨论】:

    【解决方案2】:

    当有人询问有关 Android 中的日期和/或时间的问题时,我建议您查看 ThreeTenABP 库。它为 Android 提供了现代 Java 日期和时间类。这些通常比过时的DateSimpleDateFormatCalendar 对程序员更友好。

    在你的情况下,我更愿意这样做。你没有一年。您可以使用不太好的旧GregorianCalendar 设置年份,但如果选择哪一年的要求变得有点复杂,您会更喜欢使用现代类。这是一个示例,我发现最近一年的星期几与字符串中的星期几匹配,就像一个示例,因为这可能不符合您的确切要求。我首先将字符串解析为TemporalAccessor,我认为这是最终创建我们想要的对象的一种中间形式。从这里我得到星期、月份和日期,并找到有效的年份。根据这些片段,我们将日期放在一起,然后根据解析结果,我们花时间(11:18)构建LocalDateTime,即最终结果。

        String actualDateString = "Saturday, June 10 11:18 AM";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMMM dd HH:mm a", Locale.ENGLISH);
    
        // Step one, porse
        TemporalAccessor parsed = formatter.parse(actualDateString);
        // Use day of week, month and day and find a year that matches
        DayOfWeek actualDayOfWeek = DayOfWeek.from(parsed);
        MonthDay actualMonthDay = MonthDay.from(parsed);
        int cancidateYear = Year.now(ZoneId.systemDefault()).getValue();
        while (! actualMonthDay.atYear(cancidateYear).getDayOfWeek().equals(actualDayOfWeek)) {
            cancidateYear--;
        }
    
        // Final step, put the date and time together from the pieces
        LocalDateTime dateTime = LocalDateTime.of(actualMonthDay.atYear(cancidateYear), 
                                                  LocalTime.from(parsed));
    
        System.out.println(dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    

    打印出来:

    2017-06-10 11:18:00
    

    如果您想要与星期几匹配的下一年,只需在循环中向上计数而不是向下计数。如果需要,现代类很适合使用更精细的算法来确定年份。

    感谢 Hugo,帮助我简化(再一次)。

    链接

    【讨论】:

    • 好!但实际上您不需要创建第二个解析器。你可以这样做:LocalDateTime.of(actualMonthDay.atYear(cancidateYear), LocalTime.from(parsed))
    • 谢谢,@雨果!我在想这样的事情应该是可能的,但没有完成。
    【解决方案3】:

    如 cmets 中所述,您缺少年份值,因此您将获得默认值 1970(unix 纪元值)。解析后可以使用Calendar设置年份。

    Calendar cal = Calendar.getInstance();
    SimpleDateFormat format = new SimpleDateFormat("EEEE, MMMM dd HH:mm aa", Locale.ENGLISH);
    cal.setTime(format.parse("Saturday, June 10 11:18 AM"));
    cal.set(Calendar.YEAR, 2017);
    System.out.println("date is ["+cal.getTime() +"]");
    

    【讨论】:

      【解决方案4】:

      试试这个,它对我有用:

              SimpleDateFormat sdf = new SimpleDateFormat("EEEE, MMMM dd HH:mm aa");
              Log.d("date:","date is:"+sdf.format(new java.util.Date()));
      

      【讨论】:

      • 请解释一下它会有什么帮助。仅代码答案很少有帮助。
      • 如果询问者“实际日期”的意思是“今天的日期”,它确实给出了那个(只是不是以 yyyy-MM-dd HH:mm:ss 的所需格式)。就我而言,我将问题理解为如何从上述格式的字符串中获取日期(和时间)(今天的日期只是一个例子)。
      • 在我的电脑上输出:date is:lørdag, juni 10 09:17 AM。我建议您指定明确的语言环境。
      猜你喜欢
      • 1970-01-01
      • 2018-05-27
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-25
      相关资源
      最近更新 更多