使用Dozer将XMLGregorianCalendar映射到Calendar

时间:2015-05-26 15:30:42

标签: java date calendar dozer

先决条件

推土机5.5.1

代码

    public class Testdata {

            public static final Calendar CALENDAR_EXPECTATION;
            public static final XMLGregorianCalendar XMLGREGORIANCALENDAR_INPUT;

            static {
                    CALENDAR_EXPECTATION = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris"), Locale.GERMANY);
                    CALENDAR_EXPECTATION.clear();
                    CALENDAR_EXPECTATION.set(2015, 1, 2, 13, 15, 22);

                    XMLGREGORIANCALENDAR_INPUT = XMLGregorianCalendarImpl.createDateTime(2015,
                                                                                            1,
                                                                                            2,
                                                                                            13,
                                                                                            15,
                                                                                            22,
                                                                                            0,
                                                                                            (CALENDAR_EXPECTATION.get(Calendar.ZONE_OFFSET)
                                                                                            + CALENDAR_EXPECTATION.get(Calendar.DST_OFFSET))
                                                                                            / (60 * 1000));
            }
    }


    public class MappingTest {

            @Autowired
            private org.dozer.DozerBeanMapper dozerBeanMapper;

            private static x.y.z.ClassToMap classToMap;

            @BeforeClass
            public static void setupModel() throws Exception {
                    classToMap = new ClassToMap(Testdata.XMLGREGORIANCALENDAR_INPUT);
            }

            @Test
            public void testTransaktionsInfoToTransaktionsInfo(){
                    final x.y.MyMappedClass mapped =
                            dozerBeanMapper.map(classToMap, x.y.MyMappedClass.class);

                    compareCalendar(mapped.getMyCalendar(), Testdata.CALENDAR_EXPECTATION);
            }

            private void compareCalendar(Calendar ergebnis, Calendar erwartung) {
                    assertThat(ergebnis, notNullValue());
                    assertThat(ergebnis.get(Calendar.YEAR), is(erwartung.get(Calendar.YEAR)));
                    assertThat(ergebnis.get(Calendar.MONTH), is(erwartung.get(Calendar.MONTH)));
                    assertThat(ergebnis.get(Calendar.DAY_OF_MONTH), is(erwartung.get(Calendar.DAY_OF_MONTH)));
                    assertThat(ergebnis.get(Calendar.HOUR), is(erwartung.get(Calendar.HOUR)));
                    assertThat(ergebnis.get(Calendar.MINUTE), is(erwartung.get(Calendar.MINUTE)));
                    assertThat(ergebnis.get(Calendar.SECOND), is(erwartung.get(Calendar.SECOND)));
                    assertThat(ergebnis.get(Calendar.MILLISECOND), is(erwartung.get(Calendar.MILLISECOND)));
                    assertThat(ergebnis.getTimeZone(), is(erwartung.getTimeZone()));
            }
    }

问题

断言assertThat(ergebnis.get(Calendar.MONTH), is(erwartung.get(Calendar.MONTH)));失败。 问题是期望的月份是正确的(1)但映射的日历包含(0)。

在org.dozer.converters.CalendarConverter中发生以下情况:

...
} else if (XMLGregorianCalendar.class.isAssignableFrom(srcFieldClass)) {
  Calendar c = ((XMLGregorianCalendar) srcObj).toGregorianCalendar();
  result.setTime(c.getTime());
  result.setTimeZone(c.getTimeZone());
}
...

日历c包含错误的月份(= 0)。 并调用result.setTime(c.getTime());还包含month = 0。

我应该编写自己的转换器来解决这个问题吗? 以及如何解决问题?

提前致谢。

此致

最高

1 个答案:

答案 0 :(得分:0)

对于XMLGregorianCalendar 1月对应 1 12月对应 12 ,您的测试到目前为止还可以:

  

月: 1到12或DatatypeConstants.FIELD_UNDEFINED

但是,Calendar具有从零开始的月份,这意味着 1月对应于 0 12月对应于 11

  

格里高利和朱利安日历中的第一个月是1月,即0;最后一个取决于一年中的月数。

换句话说,你的断言是错误的。您正在创建一个XMLGregorianCalendar月份一月,以及一个断言,假设它是二月。 Dozer中的convert方法看起来是正确的。

您应该使用Calendar提供的constants,这与计数是以 0 还是 1 开头无关:

CALENDAR_EXPECTATION = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris"), Locale.GERMANY);
CALENDAR_EXPECTATION.clear();
CALENDAR_EXPECTATION.set(2015, Calendar.JANUARY, 2, 13, 15, 22);