package eu.dnetlib.openaire.common; import java.text.FieldPosition; import java.util.*; import com.fasterxml.jackson.databind.util.StdDateFormat; public class RFC3339DateFormat extends StdDateFormat { private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); // Same as ISO8601DateFormat but serializing milliseconds. @Override public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { String value = format(date, true, TIMEZONE_Z, Locale.US); toAppendTo.append(value); return toAppendTo; } /** * Format date into yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm] * * @param date the date to format * @param millis true to include millis precision otherwise false * @param tz timezone to use for the formatting (UTC will produce 'Z') * @return the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm] */ private static String format(Date date, boolean millis, TimeZone tz, Locale loc) { Calendar calendar = new GregorianCalendar(tz, loc); calendar.setTime(date); // estimate capacity of buffer as close as we can (yeah, that's pedantic ;) StringBuilder sb = new StringBuilder(30); sb.append(String.format( "%04d-%02d-%02dT%02d:%02d:%02d", calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND) )); if (millis) { sb.append(String.format(".%03d", calendar.get(Calendar.MILLISECOND))); } int offset = tz.getOffset(calendar.getTimeInMillis()); if (offset != 0) { int hours = Math.abs((offset / (60 * 1000)) / 60); int minutes = Math.abs((offset / (60 * 1000)) % 60); sb.append(String.format("%c%02d:%02d", (offset < 0 ? '-' : '+'), hours, minutes)); } else { sb.append('Z'); } return sb.toString(); } }