Java 字符串日期到 xmlgregoriancalendar 的转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20970088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:38:38  来源:igfitidea点击:

String date to xmlgregoriancalendar conversion

javastringdate

提问by JavaStudent

I have written this function :

我写了这个函数:

public static XMLGregorianCalendar getXMLGregorianCalendar(String date) throws OmniException{
    XMLGregorianCalendar xmlCalender=null;
    GregorianCalendar calender = new GregorianCalendar();
    calender.setTime(Util.stringToJavaDate(date));
    xmlCalender = DatatypeFactory.newInstance().newXMLGregorianCalendar(calender);
    return xmlCalender;
}

public static Date  stringToJavaDate(String sDate)  throws OmniException{
    Date date=null;
    date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).parse(sDate);        
    return date;  
}

When i am passing date as "2014-01-07"am getting output date as 2014-01-06T18:30:00:000Zwhere i am going wrong ? also what to do if I want to get only 2014-01-06T18:30:00and 2014-01-06T18:30:00Z
Any help is appreciated

当我通过日期作为"2014-01-07"获取输出日期作为2014-01-06T18:30:00:000Z我出错的地方时?还做什么,如果我想只得到2014-01-06T18:30:002014-01-06T18:30:00Z
任何帮助表示赞赏

采纳答案by JavaStudent

Found the solution as below.... posting it as it could help somebody else too :)

找到如下解决方案....发布它,因为它也可以帮助其他人:)

DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = format.parse("2014-04-24 11:15:00");

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);

XMLGregorianCalendar xmlGregCal =  DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);

System.out.println(xmlGregCal);

Output:

输出:

2014-04-24T11:15:00.000+02:00

2014-04-24T11:15:00.000+02:00

回答by regulus001

GregorianCalendar c = GregorianCalendar.from((LocalDate.parse("2016-06-22")).atStartOfDay(ZoneId.systemDefault()));
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

回答by gil.fernandes

For me the most elegant solution is this one:

对我来说,最优雅的解决方案是这个:

XMLGregorianCalendar result = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar("2014-01-07");

Using Java 8.

使用 Java 8。

Extended example:

扩展示例:

XMLGregorianCalendar result = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar("2014-01-07");
System.out.println(result.getDay());
System.out.println(result.getMonth());
System.out.println(result.getYear());

This prints out:

这打印出来:

7
1
2014

回答by Basil Bourque

tl;dr

tl;博士

  • Use modern java.timeclasses as much as possible, rather than the terrible legacy classes.
  • Always specify your desired/expected time zone or offset-from-UTC rather than rely implicitly on JVM's current default.
  • 尽可能多地使用现代java.time类,而不是可怕的遗留类。
  • 始终指定您想要/期望的时区或从 UTC 的偏移量,而不是隐式依赖 JVM 的当前默认值。

Example code (without exception-handling):

示例代码(无异常处理):

XMLGregorianCalendar xgc = 
    DatatypeFactory                           // Data-type converter.
    .newInstance()                            // Instantiate a converter object.
    .newXMLGregorianCalendar(                 // Converter going from `GregorianCalendar` to `XMLGregorianCalendar`.
        GregorianCalendar.from(               // Convert from modern `ZonedDateTime` class to legacy `GregorianCalendar` class.
            LocalDate                         // Modern class for representing a date-only, without time-of-day and without time zone.
            .parse( "2014-01-07" )            // Parsing strings in standard ISO 8601 format is handled by default, with no need for custom formatting pattern. 
            .atStartOfDay( ZoneOffset.UTC )   // Determine the first moment of the day as seen in UTC. Returns a `ZonedDateTime` object.
        )                                     // Returns a `GregorianCalendar` object.
    )                                         // Returns a `XMLGregorianCalendar` object.
;

Parsing date-only input string into an object of XMLGregorianCalendarclass

将仅限日期的输入字符串解析为XMLGregorianCalendar类的对象

Avoid the terrible legacy date-time classes whenever possible, such as XMLGregorianCalendar, GregorianCalendar, Calendar, and Date. Use only modern java.timeclasses.

避免可怕的遗产日期时类只要有可能,例如XMLGregorianCalendarGregorianCalendarCalendar,和Date。仅使用现代java.time类。

When presented with a string such as "2014-01-07", parse as a LocalDate.

当出现诸如 之类的字符串时"2014-01-07",解析为LocalDate.

LocalDate.parse( "2014-01-07" )

To get a date with time-of-day, assuming you want the first moment of the day, specify a time zone. Let java.timedetermine the first moment of the day, as it is not always 00:00:00.0 in some zones on some dates.

要获取包含时间的日期,假设您想要一天中的第一个时刻,请指定一个时区。让java.time确定一天中的第一个时刻,因为在某些日期的某些区域中,它并不总是 00:00:00.0。

LocalDate.parse( "2014-01-07" )
         .atStartOfDay( ZoneId.of( "America/Montreal" ) )

This returns a ZonedDateTimeobject.

这将返回一个ZonedDateTime对象。

ZonedDateTime zdt = 
        LocalDate
        .parse( "2014-01-07" )
        .atStartOfDay( ZoneId.of( "America/Montreal" ) )
;

zdt.toString() = 2014-01-07T00:00-05:00[America/Montreal]

zdt.toString() = 2014-01-07T00:00-05:00[美国/蒙特利尔]

But apparently, you want the start-of-day as seen in UTC (an offset of zero hours-minutes-seconds). So we specify ZoneOffset.UTCconstant as our ZoneIdargument.

但显然,您想要在 UTC 中看到的一天开始(零时分秒的偏移量)。所以我们指定ZoneOffset.UTC常量作为我们的ZoneId参数。

ZonedDateTime zdt = 
        LocalDate
        .parse( "2014-01-07" )
        .atStartOfDay( ZoneOffset.UTC )
;

zdt.toString() = 2014-01-07T00:00Z

zdt.toString() = 2014-01-07T00:00Z

The Zon the end means UTC (an offset of zero), and is pronounced “Zulu”.

Z对端装置UTC(零偏移量),并且被读作“祖鲁”。

If you must work with legacy classes, convert to GregorianCalendar, a subclass of Calendar.

如果您必须使用遗留类,请转换为GregorianCalendar, 的子类Calendar

GregorianCalendar gc = GregorianCalendar.from( zdt ) ;

gc.toString() = java.util.GregorianCalendar[time=1389052800000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2014,MONTH=0,WEEK_OF_YEAR=2,WEEK_OF_MONTH=2,DAY_OF_MONTH=7,DAY_OF_YEAR=7,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]

gc.toString() = java.util.GregorianCalendar[time=1389052800000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings= 0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2014,MONTH=0,WEEK_OF_YEAR=2,WEEK_OF_MONTH=2,DAY_OF_MONTH=7,DAY_OF_YEAR=7 ,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]

Apparently, you really need an object of the legacy class XMLGregorianCalendar. If the calling code cannot be updated to use java.time, convert.

显然,您确实需要一个遗留类的对象XMLGregorianCalendar。如果调用代码无法更新为使用java.time,请转换。

XMLGregorianCalendar xgc = 
        DatatypeFactory
        .newInstance()
        .newXMLGregorianCalendar( gc ) 
;

Actually, that code requires a try-catch.

实际上,该代码需要 try-catch。

try
{
    XMLGregorianCalendar xgc =
            DatatypeFactory
                    .newInstance()
                    .newXMLGregorianCalendar( gc );
}
catch ( DatatypeConfigurationException e )
{
    e.printStackTrace();
}

xgc = 2014-01-07T00:00:00.000Z

xgc = 2014-01-07T00:00:00.000Z

Putting that all together, with appropriate exception-handling.

将所有这些放在一起,并进行适当的异常处理。

// Given an input string such as "2014-01-07", return a `XMLGregorianCalendar` object
// representing first moment of the day on that date as seen in UTC. 
static public XMLGregorianCalendar getXMLGregorianCalendar ( String input )
{
    Objects.requireNonNull( input );
    if( input.isBlank() ) { throw new IllegalArgumentException( "Received empty/blank input string for date argument. Message # 11818896-7412-49ba-8f8f-9b3053690c5d." ) ; }
    XMLGregorianCalendar xgc = null;
    ZonedDateTime zdt = null;

    try
    {
        zdt =
                LocalDate
                        .parse( input )
                        .atStartOfDay( ZoneOffset.UTC );
    }
    catch ( DateTimeParseException e )
    {
        throw new IllegalArgumentException( "Faulty input string for date does not comply with standard ISO 8601 format. Message # 568db0ef-d6bf-41c9-8228-cc3516558e68." );
    }

    GregorianCalendar gc = GregorianCalendar.from( zdt );
    try
    {
        xgc =
                DatatypeFactory
                        .newInstance()
                        .newXMLGregorianCalendar( gc );
    }
    catch ( DatatypeConfigurationException e )
    {
        e.printStackTrace();
    }

    Objects.requireNonNull( xgc );
    return xgc ;
}

Usage.

用法。

String input = "2014-01-07";
XMLGregorianCalendar xgc = App.getXMLGregorianCalendar( input );

Dump to console.

转储到控制台。

System.out.println( "xgc = " + xgc );

xgc = 2014-01-07T00:00:00.000Z

xgc = 2014-01-07T00:00:00.000Z

Modern date-time classes versus legacy

现代日期时间类与遗留类

Table of date-time types in Java, both modern and legacy

Java 中的日期时间类型表,现代和传统

Date-time != String

日期时间 != 字符串

Do not conflate a date-time value with its textual representation. We parse strings to get a date-time object, and we ask the date-time object to generate a string to represent its value. The date-time object has no ‘format', only strings have a format.

不要将日期时间值与其文本表示混为一谈。我们解析字符串以获取日期时间对象,然后我们要求日期时间对象生成一个字符串来表示其值。日期时间对象没有“格式”,只有字符串才有格式。

So shift your thinking into two separate modes: model and presentation. Determine the date-value you have in mind, applying appropriate time zone, as the model. When you need to display that value, generate a string in a particular format as expected by the user.

因此,将您的思维转变为两种不同的模式:模型和演示。确定您想到的日期值,应用适当的时区作为模型。当您需要显示该值时,按照用户的预期生成特定格式的字符串。

Avoid legacy date-time classes

避免遗留的日期时间类

The Question and other Answers all use old troublesome date-time classes now supplanted by the java.time classes.

问题和其他答案都使用旧的麻烦的日期时间类,现在已被 java.time 类取代。

ISO 8601

ISO 8601

Your input string "2014-01-07"is in standard ISO 8601format.

您的输入字符串"2014-01-07"采用标准ISO 8601格式。

The Tin the middle separates date portion from time portion.

T从时间部分在中间中隔离日期部分。

The Zon the end is short for Zulu and means UTC.

Z上月底是短期的祖鲁语和手段UTC

Fortunately, the java.time classes use the ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.

幸运的是,java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。所以不需要指定格式模式。

LocalDate

LocalDate

The LocalDateclass represents a date-only value without time-of-day and without time zone.

LocalDate级表示没有时间一天和不同时区的日期,唯一的价值。

LocalDate ld = LocalDate.parse( "2014-01-07" ) ;

ld.toString(): 2014-01-07

ld.toString(): 2014-01-07

Start of day ZonedDateTime

一天的开始 ZonedDateTime

If you want to see the first moment of that day, specify a ZoneIdtime zone to get a moment on the timeline, a ZonedDateTime. The time zone is crucial because the date varies around the globe by zone. A few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

如果您想查看当天的第一个时刻,请指定一个ZoneId时区以获取时间轴上的时刻,一个ZonedDateTime. 时区至关重要,因为日期在全球各地因地区而异。午夜过后几分钟在巴黎法国是新的一天,而在魁北克蒙特利尔仍然是“昨天”。

Never assume the day begins at 00:00:00. Anomalies such as Daylight Saving Time (DST) means the day may begin at another time-of-day such as 01:00:00. Let java.time determine the first moment.

永远不要假设一天从 00:00:00 开始。夏令时 (DST) 等异常意味着一天可能会在一天中的另一个时间开始,例如 01:00:00。让 java.time 确定第一时刻。

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

zdt.toString(): 2014-01-07T00:00:00Z

zdt.toString(): 2014-01-07T00:00:00Z

For your desired format, generate a string using the predefined formatter DateTimeFormatter.ISO_LOCAL_DATE_TIMEand then replace the Tin the middle with a SPACE.

对于您想要的格式,使用预定义的格式化程序生成一个字符串DateTimeFormatter.ISO_LOCAL_DATE_TIME,然后用T空格替换中间的。

String output = zdt.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
                   .replace( "T" , " " ) ; 

2014-01-07 00:00:00

2014-01-07 00:00:00



About java.time

关于 java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

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

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多