【问题标题】:parse this type of date format in java? [duplicate]在java中解析这种类型的日期格式? [复制]
【发布时间】:2011-04-30 03:29:41
【问题描述】:

在 java 中解析以下日期格式的最简单方法是什么?:

2010-09-18T10:00:00.000+01:00

我在 java 中阅读了 DateFormat api,但找不到将字符串或什至这种类型的日期格式作为参数进行解析的方法?当我的意思是解析时,我的意思是我想将“日期(日月和年)”、“时间”和“时区”提取到单独的字符串对象中。

提前致谢

【问题讨论】:

  • 我认为您正在寻找正则表达式或类似的答案。我为这个特定的解决方案提供了第二个答案,其中包含一个特定的、有效的正则表达式......

标签: java date date-parsing


【解决方案1】:

另一个答案,因为您似乎专注于简单地将String 分开(恕我直言,这不是一个好主意。)让我们假设该字符串是有效的 ISO8601。你能假设它总是是你引用的形式,还是只是有效的 8601?如果是后者,你得应付these guys did这样的一堆场景。

他们提出来验证 8601 替代方案的正则表达式是:

^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])
 (-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])
 ((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?
 ([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$ 

弄清楚如何挑选出正确的捕获组让我头晕目眩。不过,以下内容适用于您的具体情况:

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Regex8601
{
  static final Pattern r8601 = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})T((\\d{2}):"+
                               "(\\d{2}):(\\d{2})\\.(\\d{3}))((\\+|-)(\\d{2}):(\\d{2}))");


  //2010-09-18T10:00:00.000+01:00

  public static void main(String[] args)
  {
    String thisdate = "2010-09-18T10:00:00.000+01:00";
    Matcher m = r8601.matcher(thisdate);
    if (m.lookingAt()) {
      System.out.println("Year: "+m.group(1));
      System.out.println("Month: "+m.group(2));
      System.out.println("Day: "+m.group(3));
      System.out.println("Time: "+m.group(4));
      System.out.println("Timezone: "+m.group(9));
    } else {
      System.out.println("no match");
    }
  }
}

【讨论】:

  • 我打电话给一个网络服务,它向我发送一个 8601 格式的日历事件日期,然后让我分别显示时间、日期和时区。我知道如果这是他们想要显示信息的方式,他们为什么不能从自己的角度来做这件事
  • 另外:我自己正在使用这些:private static final String REG_EX_DATE = "(.*)T";私有静态最终字符串 REG_EX_TIME = "T(.*)+";私有静态最终字符串 REG_EX_TIMEZONE = "+|-(.*)";
  • 无论如何我都会尝试上面的代码,为此欢呼
  • 不,上面的代码没有工作。如果您愿意,可以在这里尝试:regexplanet.com/simple/index.html 我会尝试您发布的第一个 reg ex
  • 我对 regexplant 的事情一无所知。上面的代码在我的 JDK 上编译并运行良好,给我年份:2010 月:09 日:18 时间:10:00:00.000 时区:01:00
【解决方案2】:

如果您对日期和时间做任何重要的事情,建议使用JodaTime。见this extensive SO discussion,包括ISO8601。另见"Should I use native data/time..."

这是一个示例代码 sn-p,取自 this example,如果你想使用 JDK SimpleDateFormat

// 2004-06-14T19:GMT20:30Z
// 2004-06-20T06:GMT22:01Z

// http://www.cl.cam.ac.uk/~mgk25/iso-time.html
//    
// http://www.intertwingly.net/wiki/pie/DateTime
//
// http://www.w3.org/TR/NOTE-datetime
//
// Different standards may need different levels of granularity in the date and
// time, so this profile defines six levels. Standards that reference this
// profile should specify one or more of these granularities. If a given
// standard allows more than one granularity, it should specify the meaning of
// the dates and times with reduced precision, for example, the result of
// comparing two dates with different precisions.

// The formats are as follows. Exactly the components shown here must be
// present, with exactly this punctuation. Note that the "T" appears literally
// in the string, to indicate the beginning of the time element, as specified in
// ISO 8601.

//    Year:
//       YYYY (eg 1997)
//    Year and month:
//       YYYY-MM (eg 1997-07)
//    Complete date:
//       YYYY-MM-DD (eg 1997-07-16)
//    Complete date plus hours and minutes:
//       YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
//    Complete date plus hours, minutes and seconds:
//       YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
//    Complete date plus hours, minutes, seconds and a decimal fraction of a
// second
//       YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)

// where:

//      YYYY = four-digit year
//      MM   = two-digit month (01=January, etc.)
//      DD   = two-digit day of month (01 through 31)
//      hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
//      mm   = two digits of minute (00 through 59)
//      ss   = two digits of second (00 through 59)
//      s    = one or more digits representing a decimal fraction of a second
//      TZD  = time zone designator (Z or +hh:mm or -hh:mm)
public static Date parse( String input ) throws java.text.ParseException 
{
  //NOTE: SimpleDateFormat uses GMT[-+]hh:mm for the TZ which breaks
  //things a bit.  Before we go on we have to repair this.
  SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssz" );

  //this is zero time so we need to add that TZ indicator for 
  if ( input.endsWith( "Z" ) ) {
    input = input.substring( 0, input.length() - 1) + "GMT-00:00";
  } else {
    int inset = 6;

    String s0 = input.substring( 0, input.length() - inset );
    String s1 = input.substring( input.length() - inset, input.length() );    

    input = s0 + "GMT" + s1;
  }

  return df.parse( input );        
}

【讨论】:

  • 您不必在时区之前插入 GMT。您只需要格式字符串中的XXX 而不是z
【解决方案3】:

这个日期在ISO 8601 format。这是a link to a parser specific to this format,它在内部使用Java SimpleDateFormat 解析API。

【讨论】:

  • 嗨,我想我没有正确解释自己。我得到一个与我发布的格式相同的字符串。我想要做的是将字符串分成“日期(年、月、日)”、“时间”和“时区”。
  • 在上述 API 上调用 parse() 后,您将拥有一个 Java java.util.Date 对象。这应该足以让你弄清楚如何做你想做的事。您还需要查看 Java java.util.Calendar 类 API。
  • @jonney -- 在这种情况下,您可以使用正则表达式或简单的字符串切片来分隔字符串。但这将是非常脆弱的。我认为使用日历实现会更好地对待您。
【解决方案4】:

你应该使用SimpleDateFormat

查找示例 herehere 以开始使用。

【讨论】:

    【解决方案5】:

    您可以使用javax.xml.datatype.DatatypeFactory#newXMLGregorianCalendar(String lexicalRepresentation) (API docs)。返回的 XMLGregorianCalendar 使您可以访问所有单独的字段。

    【讨论】:

      【解决方案6】:

      使用SimpleDateFormat,模式为yyy-MM-dd'T'HH:mm:ss.SSSZ


      更新 SimpleDateFormat 不适用于 ISO 8601 日期格式。而是使用JodaTime。它提供符合 ISO 8601 的ISOChronology

      可以在SO 上找到简要示例。

      【讨论】:

      • 那行不通。 SimpleDateFormat 使用 RFC 822 来格式化时区,而该示例有一个符合 ISO 8601 的时区字符串。这些不兼容。
      • 为什么“SimpleDateFormat 不适用于 ISO 8601 日期格式”?看我的回答,有什么问题?
      • @Vladimir Prudnikov,您的格式化程序不会考虑时区差异。如何解析日期格式末尾的+01:00
      • @Buhake Sindi 你是什么意思?看一下代码,我执行了它并将“2010-09-18T10:00:00.000+01:00”解析为“Sat Sep 18 11:00:00 CEST 2010”,有一个时区 +01:00结果小时值变为 11,而不是 10。至于我,一切都很好。
      【解决方案7】:

      最简单的解决办法是这样的:

      Date date = null;
      SimpleDateFormat isoFormatWithMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
      try {
          date = isoFormatWithMillis.parse("2010-09-18T10:00:00.000+01:00");
      } catch (ParseException e) {
          e.printStackTrace();
      }
      System.out.println(date);
      

      这将打印Sat Sep 18 11:00:00 CEST 2010

      【讨论】:

        【解决方案8】:

        如果您使用的是 Java 7 或更早版本,可以参考此post

        如果您使用的是 Java 8,您可以这样做:

            DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
            TemporalAccessor accessor = timeFormatter.parse("2015-10-27T16:22:27.605-07:00");
        
            Date date = Date.from(Instant.from(accessor));
            System.out.println(date);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-03-07
          • 2018-08-31
          • 1970-01-01
          • 2015-12-26
          • 1970-01-01
          • 1970-01-01
          • 2013-01-09
          相关资源
          最近更新 更多