【问题标题】:Check date inside a html code检查 html 代码中的日期
【发布时间】:2018-01-17 13:08:57
【问题描述】:

我有一个带有类似标签的网页:“Table last updated on Thu Jul 27 10:57:10 CEST 2017 from OWNER”

我必须检查这个日期是否晚于今天的 0 点。 我正在获取 html 代码:

Document doc = Jsoup.parse(driver.getPageSource());
String htmlcode = doc.body().text();

我曾考虑对代码进行子串化以获取日期,但由于此标签值的大小可能不同,因此我无法获取整个标签。 关于如何从代码中获取日期的任何想法,以便我进行比较?

【问题讨论】:

    标签: java html date parsing jsoup


    【解决方案1】:

    tl;博士

    ZonedDateTime.parse(                              // Parse string into a date + time-of-day + time zone.
        … ,                                           // Your input string.
        DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss zzz uuuu" , Locale.US )  // Specify `Locale` to determine human language and cultural norms in parsing and translating the text.    
    )
    .toLocalDate()                                    // Extract the date-only portion of the `ZonedDateTime` object.
    .isEqual( 
        LocalDate.now( ZoneId.of( "Africa/Tunis" ) )  // Get current date as seen by people of a certain region (time zone).
    )
    

    java.time

    Answer by aUserHimself 建议使用 jsoup 库是正确的。但是示例代码在其他方面是不明智的,会犯以下几个错误:

    • 使用麻烦的旧日期时间类。这些类现在被java.time 类所取代。
    • 假设一天从 00:00:00 开始。并非所有时区的所有日期都是如此。诸如Daylight Saving Time (DST) 之类的异常意味着一天可能开始于诸如 01:00:00 之类的时间。
    • 忽略Locale的问题,它决定了解析月份名称、星期名称等文本时使用的人类语言。Locale也决定了预期的标点符号和其他文化规范.
    • 在确定当前日期时忽略了time zone 的关键问题。

    示例代码。

    String input = … ;
    Locale locale = Locale.US ;
    DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss zzz uuuu" , locale ) ;
    ZonedDateTime zdt = ZonedDateTime.parse( input , f ) ;
    LocalDate ld = zdt.toLocalDate() ; 
    

    与今天的日期进行比较。必须指定预期/期望的时区。对于任何给定的时刻,日期在世界各地因地区而异。例如,印度的新一天比加拿大早。

    ZoneId z = ZoneId.of( "America/Montreal" ) ; 
    LocalDate today = LocalDate.now( z ) ;
    
    Boolean isSameDate = ld.isEqual( today ) ;
    

    关于java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

    Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    使用符合JDBC 4.2 或更高版本的JDBC driver,您可以直接与您的数据库交换java.time 对象。不需要字符串或 java.sql.* 类。

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      【解决方案2】:

      尝试这样的事情(Java 8 之前):

          // get the label content as text (assuming you only have 1 label)
          Document doc = Jsoup.parse(driver.getPageSource());
          Element label = doc.select("label").first();
          String labelText = label.text();
      
          // get the relevant part (the date) from label content (between "on" and "from")
          String dateString = labelText.split("on")[1].split("from")[0].trim();
      
          // parse date
          SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy", Locale.ENGLISH);
          java.util.Date date = simpleDateFormat.parse(dateString);
      
          // create calendar from label date
          Calendar calendarLabel = new GregorianCalendar();
          calendarLabel.setTime(date);
      
          // create calendar for beginning of today in the default time zone
          //Calendar calendarToday = Calendar.getInstance();
          //  or in a timezone of your choice
          Calendar calendarToday = Calendar.getInstance(TimeZone.getTimeZone("Europe/Athens"));
          calendarToday.set(Calendar.HOUR_OF_DAY, 0);
          calendarToday.set(Calendar.MINUTE, 0);
          calendarToday.set(Calendar.SECOND, 0);
          calendarToday.set(Calendar.MILLISECOND, 0);
      
          // find out if label date is later than 0h of today
          System.out.println(calendarLabel.compareTo(calendarToday) >= 1);
      

      有关Java 8 中更简洁的解决方案,请参阅this answer of Basil Bourque

      【讨论】:

      • 这段代码使用了麻烦的旧日期时间类,这些类现在是遗留的,被 java.time 类所取代。另一个问题:此代码假定一天从 00:00:00 开始,对于所有区域的所有日期,并非总是如此。
      • @Basil Bourque 我同意我错过了一些细节,因为我假设所有日期都在同一个区域中,并且Java 8 中有更新的课程可供使用。我已经更新了我的答案,感谢您提出所有这些问题!我也赞成你的回答。
      • 不是在挑剔你,但像 CET 这样的 3-4 个字母的伪时区不是实际时区。它们没有标准化。他们甚至不是独一无二的! Real time zone names 的格式为continent/region,例如Asia/KolkataPacific/AucklandAfrica/Casablanca
      • 没问题,我从来没有意识到这一点。我会相应地更新我的答案。在任何情况下都非常令人困惑,因为CEST 在上面的 html 示例中也用作有效时区。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      • 1970-01-01
      相关资源
      最近更新 更多