2

i have a XML Jaxb class to set with XMLGregorianCalendar type. But we are supposed to set only year in this attribute.

XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(new 
GregorianCalendar());
xmlCal.setYear(2021);
xmlObject.setBuiltYear(xmlCal); 
// xmlCal.getYear() will give me year but its type int , so setter method not accepting it. If 
has to be of type XMLGregorianCalendar  only with year.

If i set it like above its giving 2021-09-23T10:19:38.346-04:00 but i need only year with type XMLGregorianCalendar . how we can do that ?

Spectric
  • 30,714
  • 6
  • 20
  • 43
VKP
  • 589
  • 1
  • 8
  • 34
  • 1
    Just setting the year asyou do should be enough. The XSD type should be a year, so converting it to XML should leave out the other fields. – M. Deinum Sep 23 '21 at 14:42
  • But in XSD its XMLGregorianCalendar which i cannot change – VKP Sep 23 '21 at 14:49
  • 1
    No it isn't. XSD isn't Java, it is the desciptor on which this java code was generated and also used for mapping it back. I strongly suggest to readup on what an XSD is. All date/time types in XML (without type converters) will endup as an `XMLGregorianCalendar`. Just set it as you do now, JAXB should in the end only output the date. – M. Deinum Sep 23 '21 at 14:50

2 Answers2

4

Use XMLGregorianCalendar#clear before setting the year.

Demo:

import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class Main {
    public static void main(String[] args) throws DatatypeConfigurationException {
        XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar());
        xmlCal.clear();
        xmlCal.setYear(2021);
        System.out.println(xmlCal);
    }
}

Output:

2021

ONLINE DEMO

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • 1
    Thanks That works – VKP Sep 23 '21 at 15:25
  • I suggest you use the no-arg factory method: `XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar();`. This gives you an `XMLGregorianCalendar` with all fields undefined or `null` so you won’t need `clear()`. – Ole V.V. Sep 29 '21 at 03:29
2

The answer by Arvind Kumar Avinash is good and correct. There are other ways to obtain the same, so as a supplement I am presenting a couple.

Edit: A simpler and shorter variant of the code by Arvind Kumar Avinash:

    XMLGregorianCalendar xmlCal
            = DatatypeFactory.newInstance().newXMLGregorianCalendar();
    xmlCal.setYear(2021);
    System.out.println(xmlCal);

Output:

2021

The no-arg newXMLGregorianCalendar() gives us an XMLGregorianCalendar with all fields undefined or null. Set the year, and we’re done.

You may also create your desired XMLGregorianCalendar fully complete directly from a factory method call. Here’s a longish variant:

    XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendarDate(2021, DatatypeConstants.FIELD_UNDEFINED,
                    DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED);

The result is the same as before. The fields that I set undefined are month, day of month and UTC offset (called timezone with XMLGregorianCalendar).

A much shorter variant is:

    XMLGregorianCalendar xmlCal
            = DatatypeFactory.newInstance().newXMLGregorianCalendar("2021");

Output is still the desired:

2021

Just as you want an XMLGregorianCalendar for the purpose of producing a specific string, the XMLGregorianCalendar can also be constructed from the string you want.

In case you had your year in an int, you may convert first:

    int year = 2021;
    XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(String.valueOf(year));

It may feel like a waste to convert your int to a String only to have it parsed again. You decide.

Which way to prefer? It’s a matter of taste.

java.time.Year

As an aside, only if your class requires an XMLGregorianCalendar, use that class. For all other purposes I recommend the Year class:

    Year year = Year.of(2021);
    System.out.println(year);

2021

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161