/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlgraphics.util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public final class DateFormatUtil {
private static final String ISO_8601_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
private DateFormatUtil() {
}
Formats the date according to PDF format. See section 3.8.2 of the PDF 1.4 specification.
Params: - date – The date time to format
- timeZone – The time zone used to format the date
Returns: a formatted date according to PDF format (based on ISO 8824)
/**
* Formats the date according to PDF format. See section 3.8.2 of the PDF 1.4 specification.
* @param date The date time to format
* @param timeZone The time zone used to format the date
* @return a formatted date according to PDF format (based on ISO 8824)
*/
public static String formatPDFDate(Date date, TimeZone timeZone) {
DateFormat dateFormat = createDateFormat("'D:'yyyyMMddHHmmss", timeZone);
return formatDate(date, dateFormat, '\'', true);
}
Formats the date according to ISO 8601 standard.
Params: - date – The date time to format
- timeZone – The time zone used to format the date
Returns: a formatted date according to ISO 8601
/**
* Formats the date according to ISO 8601 standard.
* @param date The date time to format
* @param timeZone The time zone used to format the date
* @return a formatted date according to ISO 8601
*/
public static String formatISO8601(Date date, TimeZone timeZone) {
DateFormat dateFormat = createDateFormat(ISO_8601_DATE_PATTERN, timeZone);
return formatDate(date, dateFormat, ':', false);
}
private static DateFormat createDateFormat(String format, TimeZone timeZone) {
DateFormat dateFormat = new SimpleDateFormat(format, Locale.ENGLISH);
dateFormat.setTimeZone(timeZone);
return dateFormat;
}
Formats the date according to the specified format and returns as a string.
Params: - date – The date / time object to format
- dateFormat – The date format to use when outputting the date
- delimiter – The character used to separate the time zone difference hours and minutes
- endWithDelimiter – Determines whether the date string will end with the delimiter character
Returns: the formatted date string
/**
* Formats the date according to the specified format and returns as a string.
* @param date The date / time object to format
* @param dateFormat The date format to use when outputting the date
* @param delimiter The character used to separate the time zone difference hours and minutes
* @param endWithDelimiter Determines whether the date string will end with the delimiter character
* @return the formatted date string
*/
private static String formatDate(Date date, DateFormat dateFormat, char delimiter,
boolean endWithDelimiter) {
Calendar cal = Calendar.getInstance(dateFormat.getTimeZone(), Locale.ENGLISH);
cal.setTime(date);
int offset = getOffsetInMinutes(cal);
StringBuilder sb = new StringBuilder(dateFormat.format(date));
appendOffset(sb, delimiter, offset, endWithDelimiter);
return sb.toString();
}
private static int getOffsetInMinutes(Calendar cal) {
int offset = cal.get(Calendar.ZONE_OFFSET);
offset += cal.get(Calendar.DST_OFFSET);
offset /= (1000 * 60);
return offset;
}
private static void appendOffset(StringBuilder sb, char delimiter, int offset, boolean endWithDelimiter) {
if (offset == 0) {
appendOffsetUTC(sb);
} else {
appendOffsetNoUTC(sb, delimiter, offset, endWithDelimiter);
}
}
private static void appendOffsetUTC(StringBuilder sb) {
sb.append('Z');
}
private static void appendOffsetNoUTC(StringBuilder sb, char delimiter, int offset,
boolean endWithDelimiter) {
int zoneOffsetHours = offset / 60;
appendOffsetSign(sb, zoneOffsetHours);
appendPaddedNumber(sb, Math.abs(zoneOffsetHours));
sb.append(delimiter);
appendPaddedNumber(sb, Math.abs(offset % 60));
if (endWithDelimiter) {
sb.append(delimiter);
}
}
private static void appendOffsetSign(StringBuilder sb, int zoneOffsetHours) {
if (zoneOffsetHours >= 0) {
sb.append('+');
} else {
sb.append('-');
}
}
private static void appendPaddedNumber(StringBuilder sb, int number) {
if (number < 10) {
sb.append('0');
}
sb.append(number);
}
Parses an ISO 8601 date and time value.
Params: - date – the date and time value as an ISO 8601 string
Returns: the parsed date/time
/**
* Parses an ISO 8601 date and time value.
* @param date the date and time value as an ISO 8601 string
* @return the parsed date/time
*/
public static Date parseISO8601Date(String date) {
final String errorMessage = "Invalid ISO 8601 date format: ";
date = formatDateToParse(date, errorMessage);
DateFormat dateFormat = new SimpleDateFormat(ISO_8601_DATE_PATTERN + "Z");
try {
return dateFormat.parse(date);
} catch (ParseException ex) {
throw new IllegalArgumentException(errorMessage + date);
}
}
private static String formatDateToParse(String date, String errorMessage) {
/* Remove the colon from the time zone difference (+08:00) so that it can be parsed
* by the SimpleDateFormat string.
*/
if (!date.contains("Z")) {
int lastColonIndex = date.lastIndexOf(":");
if (lastColonIndex < 0) {
throw new IllegalArgumentException(errorMessage + date);
}
date = date.substring(0, lastColonIndex) + date.substring(lastColonIndex + 1, date.length());
} else {
date = date.replace("Z", "+0000");
}
return date;
}
}