Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.util;
  
  import java.util.*;

Utilities methods for manipulating dates in iso8601 format. This is much much faster and GC friendly than using SimpleDateFormat so highly suitable if you (un)serialize lots of date objects.
  
  public class ISO8601Utils {

    
ID to represent the 'GMT' string
 
     private static final String GMT_ID = "GMT";

    
The GMT timezone
 
     private static final TimeZone TIMEZONE_GMT = TimeZone.getTimeZone();
 
     /*
     /**********************************************************
     /* Static factories
     /**********************************************************
      */
    
    
Accessor for static GMT timezone instance.
 
     public static TimeZone timeZoneGMT() {
         return ;
     }
 
     /*
     /**********************************************************
     /* Formatting
     /**********************************************************
      */
    
    
Format a date into 'yyyy-MM-ddThh:mm:ssZ' (GMT timezone, no milliseconds precision)

Parameters:
date the date to format
Returns:
the date formatted as 'yyyy-MM-ddThh:mm:ssZ'
 
     public static String format(Date date) {
         return format(datefalse);
     }

    
Format a date into 'yyyy-MM-ddThh:mm:ss[.sss]Z' (GMT timezone)

Parameters:
date the date to format
millis true to include millis precision otherwise false
Returns:
the date formatted as 'yyyy-MM-ddThh:mm:ss[.sss]Z'
 
     public static String format(Date dateboolean millis) {
         return format(datemillis);
     }

    
Format date into yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]

Parameters:
date the date to format
millis true to include millis precision otherwise false
tz timezone to use for the formatting (GMT will produce 'Z')
Returns:
the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
 
     public static String format(Date dateboolean millisTimeZone tz) {
         Calendar calendar = new GregorianCalendar(tz.);
         calendar.setTime(date);
 
         // estimate capacity of buffer as close as we can (yeah, that's pedantic ;)
         int capacity = "yyyy-MM-ddThh:mm:ss".length();
         capacity += millis ? ".sss".length() : 0;
         capacity += tz.getRawOffset() == 0 ? "Z".length() : "+hh:mm".length();
         StringBuilder formatted = new StringBuilder(capacity);
 
         padInt(formattedcalendar.get(.), "yyyy".length());
         formatted.append('-');
         padInt(formattedcalendar.get(.) + 1, "MM".length());
         formatted.append('-');
         padInt(formattedcalendar.get(.), "dd".length());
         formatted.append('T');
         padInt(formattedcalendar.get(.), "hh".length());
         formatted.append(':');
         padInt(formattedcalendar.get(.), "mm".length());
         formatted.append(':');
         padInt(formattedcalendar.get(.), "ss".length());
         if (millis) {
             formatted.append('.');
             padInt(formattedcalendar.get(.), "sss".length());
         }
 
         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);
             formatted.append(offset < 0 ? '-' : '+');
            padInt(formattedhours"hh".length());
            formatted.append(':');
            padInt(formattedminutes"mm".length());
        } else {
            formatted.append('Z');
        }
        return formatted.toString();
    }
    /*
    /**********************************************************
    /* Parsing
    /**********************************************************
     */

    
Parse a date from ISO-8601 formatted string. It expects a format yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]

Parameters:
date ISO string to parse in the appropriate format.
Returns:
the parsed date
Throws:
java.lang.IllegalArgumentException if the date is not in the appropriate format
    public static Date parse(String date)
    {
        Exception fail = null;
        try {
            int offset = 0;
            // extract year
            int year = parseInt(dateoffsetoffset += 4);
            checkOffset(dateoffset'-');
            // extract month
            int month = parseInt(dateoffset += 1, offset += 2);
            checkOffset(dateoffset'-');
            // extract day
            int day = parseInt(dateoffset += 1, offset += 2);
            checkOffset(dateoffset'T');
            // extract hours, minutes, seconds and milliseconds
            int hour = parseInt(dateoffset += 1, offset += 2);
            checkOffset(dateoffset':');
            int minutes = parseInt(dateoffset += 1, offset += 2);
            checkOffset(dateoffset':');
            int seconds = parseInt(dateoffset += 1, offset += 2);
            // milliseconds can be optional in the format
            int milliseconds = 0; // always use 0 otherwise returned date will include millis of current time
            if (date.charAt(offset) == '.') {
                checkOffset(dateoffset'.');
                milliseconds = parseInt(dateoffset += 1, offset += 3);
            }
            // extract timezone
            String timezoneId;
            char timezoneIndicator = date.charAt(offset);
            if (timezoneIndicator == '+' || timezoneIndicator == '-') {
                timezoneId =  + date.substring(offset);
            } else if (timezoneIndicator == 'Z') {
                timezoneId = ;
            } else {
                throw new IndexOutOfBoundsException("Invalid time zone indicator " + timezoneIndicator);
            }
            TimeZone timezone = TimeZone.getTimeZone(timezoneId);
            if (!timezone.getID().equals(timezoneId)) {
                throw new IndexOutOfBoundsException();
            }
            Calendar calendar = new GregorianCalendar(timezone);
            calendar.setLenient(false);
            calendar.set(.year);
            calendar.set(.month - 1);
            calendar.set(.day);
            calendar.set(.hour);
            calendar.set(.minutes);
            calendar.set(.seconds);
            calendar.set(.milliseconds);
            return calendar.getTime();
        } catch (IndexOutOfBoundsException e) {
            fail = e;
        } catch (NumberFormatException e) {
            fail = e;
        } catch (IllegalArgumentException e) {
            fail = e;
        }
        String input = (date == null) ? null : ('"'+date+"'");
        throw new IllegalArgumentException("Failed to parse date ["+input
                +"]: "+fail.getMessage(), fail);
    }

    
Check if the expected character exist at the given offset of the

Parameters:
value the string to check at the specified offset
offset the offset to look for the expected character
expected the expected character
Throws:
java.lang.IndexOutOfBoundsException if the expected character is not found
    private static void checkOffset(String valueint offsetchar expectedthrows IndexOutOfBoundsException {
        char found = value.charAt(offset);
        if (found != expected) {
            throw new IndexOutOfBoundsException("Expected '" + expected + "' character but found '" + found + "'");
        }
    }

    
Parse an integer located between 2 given offsets in a string

Parameters:
value the string to parse
beginIndex the start index for the integer in the string
endIndex the end index for the integer in the string
Returns:
the int
Throws:
java.lang.NumberFormatException if the value is not a number
    private static int parseInt(String valueint beginIndexint endIndexthrows NumberFormatException {
        if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) {
            throw new NumberFormatException(value);
        }
        // use same logic as in Integer.parseInt() but less generic we're not supporting negative values
        int i = beginIndex;
        int result = 0;
        int digit;
        if (i < endIndex) {
            digit = Character.digit(value.charAt(i++), 10);
            if (digit < 0) {
                throw new NumberFormatException("Invalid number: " + value);
            }
            result = -digit;
        }
        while (i < endIndex) {
            digit = Character.digit(value.charAt(i++), 10);
            if (digit < 0) {
                throw new NumberFormatException("Invalid number: " + value);
            }
            result *= 10;
            result -= digit;
        }
        return -result;
    }

    
Zero pad a number to a specified length

Parameters:
buffer buffer to use for padding
value the integer value to pad if necessary.
length the length of the string we should zero pad
    private static void padInt(StringBuilder bufferint valueint length) {
        String strValue = Integer.toString(value);
        for (int i = length - strValue.length(); i > 0; i--) {
            buffer.append('0');
        }
        buffer.append(strValue);
    }
New to GrepCode? Check out our FAQ X