代码之家  ›  专栏  ›  技术社区  ›  Freiheit

带有冒号分隔符的时区的Java?

  •  58
  • Freiheit  · 技术社区  · 15 年前

    我的日期格式如下: 2010-03-01T00:00:00-08:00

    我向它抛出了以下simpledateFormats来解析它:

    private static final SimpleDateFormat[] FORMATS = {
            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"), //ISO8601 long RFC822 zone
            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"), //ISO8601 long long form zone
            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"), //ignore timezone
            new SimpleDateFormat("yyyyMMddHHmmssZ"), //ISO8601 short
            new SimpleDateFormat("yyyyMMddHHmm"),
            new SimpleDateFormat("yyyyMMdd"), //birthdate from NIST IHE C32 sample
            new SimpleDateFormat("yyyyMM"),
            new SimpleDateFormat("yyyy") //just the year
        };
    

    我有一个方便的方法,它使用这样的格式:

    public static Date figureOutTheDamnDate(String wtf) {
        if (wtf == null) {
            return null;
        }
        Date retval = null;
        for (SimpleDateFormat sdf : FORMATS) {
            try {
                sdf.setLenient(false)
                retval = sdf.parse(wtf);
                System.out.println("Date:" + wtf + " hit on pattern:" + sdf.toPattern());
                break;
            } catch (ParseException ex) {
                retval = null;
                continue;
            }
        }
    
        return retval;
    }
    

    它似乎符合模式 yyyyMMddHHmm 但返回日期为 Thu Dec 03 00:01:00 PST 2009 .

    解析这个日期的正确模式是什么?

    更新:我不需要时区分析。我不希望有时间敏感的问题在区域之间移动,但是我如何才能得到“-08:00”区域格式来解析????

    单元测试:

    @Test
    public void test_date_parser() {
        System.out.println("\ntest_date_parser");
        //month is zero based, are you effing kidding me
        Calendar d = new GregorianCalendar(2000, 3, 6, 13, 00, 00);
        assertEquals(d.getTime(), MyClass.figureOutTheDamnDate("200004061300"));
        assertEquals(new GregorianCalendar(1950, 0, 1).getTime(), MyClass.figureOutTheDamnDate("1950"));
        assertEquals(new GregorianCalendar(1997, 0, 1).getTime(),  MyClass.figureOutTheDamnDate("199701"));
        assertEquals(new GregorianCalendar(2010, 1, 25, 15, 19, 44).getTime(),   MyClass.figureOutTheDamnDate("20100225151944-0800"));
    
        //my machine happens to be in GMT-0800
        assertEquals(new GregorianCalendar(2010, 1, 15, 13, 15, 00).getTime(),MyClass.figureOutTheDamnDate("2010-02-15T13:15:00-05:00"));
        assertEquals(new GregorianCalendar(2010, 1, 15, 18, 15, 00).getTime(), MyClass.figureOutTheDamnDate("2010-02-15T18:15:00-05:00"));
    
        assertEquals(new GregorianCalendar(2010, 2, 1).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T00:00:00-08:00"));
        assertEquals(new GregorianCalendar(2010, 2, 1, 17, 0, 0).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T17:00:00-05:00"));
    }
    

    单元测试输出:

    test_date_parser
    Date:200004061300 hit on pattern:yyyyMMddHHmm
    Date:1950 hit on pattern:yyyy
    Date:199701 hit on pattern:yyyyMM
    Date:20100225151944-0800 hit on pattern:yyyyMMddHHmmssZ
    Date:2010-02-15T13:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
    Date:2010-02-15T18:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
    Date:2010-03-01T00:00:00-08:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
    Date:2010-03-01T17:00:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
    
    11 回复  |  直到 6 年前
        1
  •  56
  •   reevesy onejigtwojig    13 年前

    JodaTime DateTimeFormat 救援:

    String dateString = "2010-03-01T00:00:00-08:00";
    String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
    DateTimeFormatter dtf = DateTimeFormat.forPattern(pattern);
    DateTime dateTime = dtf.parseDateTime(dateString);
    System.out.println(dateTime); // 2010-03-01T04:00:00.000-04:00
    

    (时间和时区差异 toString() 只是因为我在格林尼治标准时间4,没有明确设置地区)

    如果你想以 java.util.Date 只是使用 DateTime#toDate() :

    Date date = dateTime.toDate();
    

    等待 JDK7 JSR-310 ) JSR-310,引用实现被称为 ThreeTen (如果希望在标准JavaSeAPI中有更好的格式化程序,希望它能进入Java 8)。当前 SimpleDateFormat 实际上,在时区符号中不吃冒号。

    更新 :根据更新,您显然不需要时区。这应该和 日期格式 . 忽略它 Z )在模式中。

    String dateString = "2010-03-01T00:00:00-08:00";
    String pattern = "yyyy-MM-dd'T'HH:mm:ss";
    SimpleDateFormat sdf = new SimpleDateFormat(pattern);
    Date date = sdf.parse(dateString);
    System.out.println(date); // Mon Mar 01 00:00:00 BOT 2010
    

    (根据我的时区是正确的)

        2
  •  33
  •   Jonathon Reinhart    11 年前

    如果使用Java 7,则可以使用以下日期时间模式。在早期版本的Java中,这种模式似乎不受支持。

    String dateTimeString  = "2010-03-01T00:00:00-08:00";
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    Date date = df.parse(dateTimeString);
    

    有关更多信息,请参阅 SimpleDateFormat documentation .

        3
  •  29
  •   acdcjunior Mukul Kumar    12 年前

    这是我用过的一个片段-简单明了 SimpleDateFormat . 希望其他人能从中受益:

    public static void main(String[] args) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") {
            public StringBuffer format(Date date, StringBuffer toAppendTo, java.text.FieldPosition pos) {
                StringBuffer toFix = super.format(date, toAppendTo, pos);
                return toFix.insert(toFix.length()-2, ':');
            };
        };
        // Usage:
        System.out.println(dateFormat.format(new Date()));
    }
    

    输出:

    - Usual Output.........: 2013-06-14T10:54:07-0200
    - This snippet's Output: 2013-06-14T10:54:07-02:00
    
        4
  •  13
  •   Rustam    8 年前

    试试这个,它对我有用:

    Date date = javax.xml.bind.DatatypeConverter.parseDateTime("2013-06-01T12:45:01+04:00").getTime();
    

    在Java 8中:

    OffsetDateTime dt = OffsetDateTime.parse("2010-03-01T00:00:00-08:00");
    
        5
  •  9
  •   Willie Z    9 年前

    如果可以使用JDK 1.7或更高版本,请尝试以下操作:

    public class DateUtil {
        private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    
        public static String format(Date date) {
            return dateFormat.format(date);
        }
    
        public static Date parse(String dateString) throws AquariusException {
            try {
                return dateFormat.parse(dateString);
            } catch (ParseException e) {
                throw new AquariusException(e);
            }
        }
    }
    

    文件: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html 它支持新的时区格式“xxx”(例如-3:00)

    而JDK 1.6只支持时区的其他格式,如“z”(如nzst)、“zzzz”(如新西兰标准时间)、“z”(如+1200)等。

        6
  •  7
  •   Basil Bourque    6 年前

    DR

    OffsetDateTime.parse( "2010-03-01T00:00:00-08:00" )
    

    细节

    这个 answer by BalusC 是正确的,但现在已经过时了,如Java 8。

    java.time时间

    这个 java.time 框架是JoDA时间库和旧的麻烦日期时间类的继承者,它与Java的最早版本捆绑在一起(Java.U.L.Deal./Realth&App.java.Text SimpleDateFormat)。

    ISO 8601标准

    您的输入数据字符串恰好符合 ISO 8601 标准。

    在分析/生成日期时间值的文本表示形式时,java.time类默认使用iso 8601格式。所以不需要定义格式化模式。

    OffsetDateTime

    这个 OffsetDateTime 类表示时间线上调整到某个特定的时刻 offset-from-UTC . 在您的输入中,偏移比UTC晚8小时,通常用于北美西海岸的大部分地区。

    OffsetDateTime odt = OffsetDateTime.parse( "2010-03-01T00:00:00-08:00" );
    

    你似乎只想要日期,在这种情况下用 LocalDate 类。但请记住,您正在丢弃数据,(a)一天中的某个时间,以及(b)时区。真的? 没有时区的上下文,日期就没有意义。 . 在任何特定的时刻,日期在世界各地都不尽相同。例如,就在午夜过后,巴黎仍然是昨天在蒙特利尔。因此,尽管我建议使用日期时间值,但您可以轻松地将其转换为 本地日期 如果你坚持的话。

    LocalDate localDate = odt.toLocalDate();
    

    时区

    如果你知道计划的时区,就应用它。时区是偏移量 用于处理异常的规则,如 Daylight Saving Time (DST) . 应用 ZoneId 给我们一个 ZonedDateTime 对象。

    ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
    ZonedDateTime zdt = odt.atZoneSameInstant( zoneId );
    

    正在生成字符串

    要生成ISO 8601格式的字符串,请调用 toString .

    String output = odt.toString();
    

    如果需要其他格式的字符串,请搜索堆栈溢出以使用 java.util.format 包裹。

    转换为 java.util.Date

    最好避免 java.util.Date ,但如果必须,可以转换。调用添加到旧类中的新方法,例如 java.util.Date.from 你经过的地方 Instant . 安 即时 时间线上的一刻 UTC . 我们可以提取 即时 从我们的 偏移日期时间 .

    java.util.Date utilDate = java.util.Date( odt.toInstant() );
    

    关于 java.time时间

    这个 java.time 框架是在Java 8和之后构建的。这些阶级取代了麻烦的旧阶级。 legacy 日期时间类,如 java.util.Date , Calendar ,& SimpleDateFormat .

    这个 Joda-Time 项目,现在在 maintenance mode ,建议迁移到 java.time 课程。

    要了解更多信息,请参阅 Oracle Tutorial . 以及搜索堆栈溢出以获得许多示例和解释。规格为 JSR 310 .

    你可以换 java.time时间 直接使用数据库的对象。使用A JDBC driver 符合 JDBC 4.2 或者以后。不需要字符串,不需要 java.sql.* 课程。

    在哪里获取java.time类?

    这个 ThreeTen-Extra Project使用其他类扩展java.time。这个项目是将来可能添加到java.time的一个试验场。您可以在这里找到一些有用的类,例如 Interval , YearWeek , YearQuarter more .

        7
  •  4
  •   Bludwarf    12 年前

    谢谢 ACDCJunior公司 为你的解决方案。这里有一个小的优化版本 格式化和解析 :

    public static final SimpleDateFormat XML_SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.FRANCE)
    {
        private static final long serialVersionUID = -8275126788734707527L;
    
        public StringBuffer format(Date date, StringBuffer toAppendTo, java.text.FieldPosition pos)
        {            
            final StringBuffer buf = super.format(date, toAppendTo, pos);
            buf.insert(buf.length() - 2, ':');
            return buf;
        };
    
        public Date parse(String source) throws java.text.ParseException {
            final int split = source.length() - 2;
            return super.parse(source.substring(0, split - 1) + source.substring(split)); // replace ":" du TimeZone
        };
    };
    
        8
  •  2
  •   bigspawn    6 年前

    可以在Java 7中使用X。

    https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

    static final SimpleDateFormat DATE_TIME_FORMAT = 
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    static final SimpleDateFormat JSON_DATE_TIME_FORMAT = 
            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    
    private String stringDate = "2016-12-01 22:05:30";
    private String requiredDate = "2016-12-01T22:05:30+03:00";
    
    @Test
    public void parseDateToBinBankFormat() throws ParseException {
        Date date = DATE_TIME_FORMAT.parse(stringDate);
        String jsonDate = JSON_DATE_TIME_FORMAT.format(date);
    
        System.out.println(jsonDate);
        Assert.assertEquals(jsonDate, requiredDate);
    }
    
        9
  •  1
  •   Community CDub    8 年前

    尝试 setLenient(false) .

    附录:看起来你正在识别不同格式的 Date 串。如果你要做输入,你可能会喜欢看这个 example 延伸 InputVerifier .

        10
  •  1
  •   Abhishek Oza    8 年前

    由于是Apache FastDateFormat的一个示例(单击可查看版本的文档: 2.6 3.5 )这里不见了,我正在给可能需要它的人加一个。这里的关键是模式 ZZ (2资本 Z s)。

    import java.text.ParseException
    import java.util.Date;
    import org.apache.commons.lang3.time.FastDateFormat;
    public class DateFormatTest throws ParseException {
        public static void main(String[] args) {
            String stringDateFormat = "yyyy-MM-dd'T'HH:mm:ssZZ";
            FastDateFormat fastDateFormat = FastDateFormat.getInstance(stringDateFormat);
            System.out.println("Date formatted into String:");
            System.out.println(fastDateFormat.format(new Date()));
            String stringFormattedDate = "2016-11-22T14:30:14+05:30";
            System.out.println("String parsed into Date:");
            System.out.println(fastDateFormat.parse(stringFormattedDate));
        }
    }
    

    下面是代码的输出:

    Date formatted into String:
    2016-11-22T14:52:17+05:30
    String parsed into Date:
    Tue Nov 22 14:30:14 IST 2016
    

    注意:上面的代码是ApacheCommons的lang3。班级 org.apache.commons.lang.time.FastDateFormat 不支持解析,只支持格式化。例如,以下代码的输出:

    import java.text.ParseException;
    import java.util.Date;
    import org.apache.commons.lang.time.FastDateFormat;
    public class DateFormatTest {
        public static void main(String[] args) throws ParseException {
            String stringDateFormat = "yyyy-MM-dd'T'HH:mm:ssZZ";
            FastDateFormat fastDateFormat = FastDateFormat.getInstance(stringDateFormat);
            System.out.println("Date formatted into String:");
            System.out.println(fastDateFormat.format(new Date()));
            String stringFormattedDate = "2016-11-22T14:30:14+05:30";
            System.out.println("String parsed into Date:");
            System.out.println(fastDateFormat.parseObject(stringFormattedDate));
        }
    }
    

    会是这样的:

    Date formatted into String:
    2016-11-22T14:55:56+05:30
    String parsed into Date:
    Exception in thread "main" java.text.ParseException: Format.parseObject(String) failed
        at java.text.Format.parseObject(Format.java:228)
        at DateFormatTest.main(DateFormatTest.java:12)
    
        11
  •  0
  •   HimalayanCoder    6 年前

    如果日期字符串类似 2018年7月20日12:18:29.802Z 使用这个

    SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");