/** * ============================================================================= * * ORCID (R) Open Source * http://orcid.org * * Copyright (c) 2012-2014 ORCID, Inc. * Licensed under an MIT-Style License (MIT) * http://orcid.org/open-source-license * * This copyright and license information (including a link to the full license) * shall be included in its entirety in all copies or substantial portion of * the software. * * ============================================================================= */ package org.orcid.utils; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import org.apache.commons.lang.StringUtils; /** * * @author Will Simpson * */ public class DateUtils { private static final Pattern DATE_PATTERN = Pattern.compile("(\\d+)(?:-(\\d+))?(?:-(\\d+))?(T\\d\\d:\\d\\d:\\d\\d)?"); //Thread safe: see source http://www.docjar.com/html/api/com/sun/org/apache/xerces/internal/jaxp/datatype/DatatypeFactoryImpl.java.html //see also analysis: http://www.javajirawat.com/2015/09/xmlgregoriancalendar-datatypefactory.html private static DatatypeFactory dataTypeFactory; /** * @see http * ://www.crossref.org/schema/info/CrossRefSchemaDocumentation4.1.0.pdf */ private static Map<String, String> seasonsAndQuartersToMonth = new HashMap<String, String>(); static { seasonsAndQuartersToMonth.put("21", "03"); seasonsAndQuartersToMonth.put("22", "06"); seasonsAndQuartersToMonth.put("23", "09"); seasonsAndQuartersToMonth.put("24", "12"); seasonsAndQuartersToMonth.put("31", "01"); seasonsAndQuartersToMonth.put("32", "04"); seasonsAndQuartersToMonth.put("33", "07"); seasonsAndQuartersToMonth.put("34", "10"); } public static XMLGregorianCalendar convertToXMLGregorianCalendar(String dateString) { return convertToXMLGregorianCalendar(dateString, true); } public static XMLGregorianCalendar convertToXMLGregorianCalendar(String dateString, boolean tidy) { String tidyDateString = dateString; if(tidy) { tidyDateString = tidy(dateString); } if (tidyDateString == null) { return null; } DatatypeFactory dataTypeFactory = createDataTypeFactory(); try { return dataTypeFactory.newXMLGregorianCalendar(tidyDateString); } catch (IllegalArgumentException e) { return null; } } public static XMLGregorianCalendar convertToXMLGregorianCalendar(long time) { GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTimeInMillis(time); return convertToXMLGregorianCalendar(gregorianCalendar); } public static XMLGregorianCalendar convertToXMLGregorianCalendar(GregorianCalendar gregorianCalendar) { return createDataTypeFactory().newXMLGregorianCalendar(gregorianCalendar); } public static XMLGregorianCalendar convertToXMLGregorianCalendar(Date date) { if (date == null) { return null; } return convertToXMLGregorianCalendar(date.getTime()); } public static XMLGregorianCalendar convertToXMLGregorianCalendarNoTimeZoneNoMillis(Date date) { XMLGregorianCalendar basicCalender = convertToXMLGregorianCalendar(date); basicCalender.setTimezone(DatatypeConstants.FIELD_UNDEFINED); basicCalender.setMillisecond(DatatypeConstants.FIELD_UNDEFINED); return basicCalender; } public static Date convertToDate(String dateString) { String tidyDateString = tidy(dateString); if (tidyDateString == null) { return null; } return convertToXMLGregorianCalendar(tidyDateString).toGregorianCalendar().getTime(); } public static Date convertToDate(XMLGregorianCalendar xmlGregorianCalendar) { if (xmlGregorianCalendar == null) { return null; } return xmlGregorianCalendar.toGregorianCalendar().getTime(); } private static String tidy(String dateString) { if (dateString == null) { return null; } Matcher matcher = DATE_PATTERN.matcher(dateString); if (!matcher.matches()) { return null; } String year = matcher.group(1); String month = matcher.group(2); String day = matcher.group(3); String time = matcher.group(4); StringBuilder builder = new StringBuilder(); builder.append(StringUtils.leftPad(year, 4, '0')); if (month != null) { builder.append('-'); month = mapSeasonsAndQuartersToMonth(month); builder.append(StringUtils.leftPad(month, 2, '0')); } if (day != null) { builder.append('-'); builder.append(StringUtils.leftPad(day, 2, '0')); } if (time != null) { builder.append(time); } return builder.toString(); } public static boolean olderThan(Date date, int days) { return date.getTime() < new Date().getTime() - days * 24 * 60 * 60 * 1000; } private static String mapSeasonsAndQuartersToMonth(String month) { if (seasonsAndQuartersToMonth.containsKey(month)) { return seasonsAndQuartersToMonth.get(month); } else { return month; } } private static DatatypeFactory createDataTypeFactory() { if (dataTypeFactory == null){ synchronized (DateUtils.class){ if (dataTypeFactory == null) try { dataTypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException e) { throw new RuntimeException("Couldn't create org.orcid.test.data type factory", e); } } } return dataTypeFactory; } }