diff --git src/java/org/apache/lucene/document/DateTools.java src/java/org/apache/lucene/document/DateTools.java
index b4db10a..b952e7b 100644
--- src/java/org/apache/lucene/document/DateTools.java
+++ src/java/org/apache/lucene/document/DateTools.java
@@ -51,27 +51,6 @@ import org.apache.lucene.util.NumericUtils; // for javadocs
 public class DateTools {
   
   private final static TimeZone GMT = TimeZone.getTimeZone("GMT");
-
-  private static final SimpleDateFormat YEAR_FORMAT = new SimpleDateFormat("yyyy");
-  private static final SimpleDateFormat MONTH_FORMAT = new SimpleDateFormat("yyyyMM");
-  private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("yyyyMMdd");
-  private static final SimpleDateFormat HOUR_FORMAT = new SimpleDateFormat("yyyyMMddHH");
-  private static final SimpleDateFormat MINUTE_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
-  private static final SimpleDateFormat SECOND_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
-  private static final SimpleDateFormat MILLISECOND_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");
-  static {
-    // times need to be normalized so the value doesn't depend on the 
-    // location the index is created/used:
-    YEAR_FORMAT.setTimeZone(GMT);
-    MONTH_FORMAT.setTimeZone(GMT);
-    DAY_FORMAT.setTimeZone(GMT);
-    HOUR_FORMAT.setTimeZone(GMT);
-    MINUTE_FORMAT.setTimeZone(GMT);
-    SECOND_FORMAT.setTimeZone(GMT);
-    MILLISECOND_FORMAT.setTimeZone(GMT);
-  }
-
-  private static final Calendar calInstance = Calendar.getInstance(GMT);
   
   // cannot create, the class has static methods only
   private DateTools() {}
@@ -81,12 +60,12 @@ public class DateTools {
    * 
    * @param date the date to be converted
    * @param resolution the desired resolution, see
-   *  {@link #round(Date, DateTools.Resolution)}
+   *  {@link #round(Date, org.apache.lucene.document.DateTools.Resolution)}
    * @return a string in format <code>yyyyMMddHHmmssSSS</code> or shorter,
    *  depeding on <code>resolution</code>; using GMT as timezone 
    */
-  public static synchronized String dateToString(Date date, Resolution resolution) {
-    return timeToString(date.getTime(), resolution);
+  public static String dateToString(Date date, Resolution resolution) {
+    return resolution.formatDate(date);
   }
 
   /**
@@ -94,31 +73,12 @@ public class DateTools {
    * 
    * @param time the date expressed as milliseconds since January 1, 1970, 00:00:00 GMT
    * @param resolution the desired resolution, see
-   *  {@link #round(long, DateTools.Resolution)}
+   *  {@link #round(long, org.apache.lucene.document.DateTools.Resolution)}
    * @return a string in format <code>yyyyMMddHHmmssSSS</code> or shorter,
    *  depeding on <code>resolution</code>; using GMT as timezone
    */
-  public static synchronized String timeToString(long time, Resolution resolution) {
-    calInstance.setTimeInMillis(round(time, resolution));
-    Date date = calInstance.getTime();
-    
-    if (resolution == Resolution.YEAR) {
-      return YEAR_FORMAT.format(date);
-    } else if (resolution == Resolution.MONTH) {
-      return MONTH_FORMAT.format(date);
-    } else if (resolution == Resolution.DAY) {
-      return DAY_FORMAT.format(date);
-    } else if (resolution == Resolution.HOUR) {
-      return HOUR_FORMAT.format(date);
-    } else if (resolution == Resolution.MINUTE) {
-      return MINUTE_FORMAT.format(date);
-    } else if (resolution == Resolution.SECOND) {
-      return SECOND_FORMAT.format(date);
-    } else if (resolution == Resolution.MILLISECOND) {
-      return MILLISECOND_FORMAT.format(date);
-    }
-    
-    throw new IllegalArgumentException("unknown resolution " + resolution);
+  public static String timeToString(long time, Resolution resolution) {
+    return dateToString(new Date(time),resolution);
   }
   
   /**
@@ -131,7 +91,7 @@ public class DateTools {
    * @throws ParseException if <code>dateString</code> is not in the 
    *  expected format 
    */
-  public static synchronized long stringToTime(String dateString) throws ParseException {
+  public static long stringToTime(String dateString) throws ParseException {
     return stringToDate(dateString).getTime();
   }
 
@@ -145,23 +105,14 @@ public class DateTools {
    * @throws ParseException if <code>dateString</code> is not in the 
    *  expected format 
    */
-  public static synchronized Date stringToDate(String dateString) throws ParseException {
-    if (dateString.length() == 4) {
-      return YEAR_FORMAT.parse(dateString);
-    } else if (dateString.length() == 6) {
-      return MONTH_FORMAT.parse(dateString);
-    } else if (dateString.length() == 8) {
-      return DAY_FORMAT.parse(dateString);
-    } else if (dateString.length() == 10) {
-      return HOUR_FORMAT.parse(dateString);
-    } else if (dateString.length() == 12) {
-      return MINUTE_FORMAT.parse(dateString);
-    } else if (dateString.length() == 14) {
-      return SECOND_FORMAT.parse(dateString);
-    } else if (dateString.length() == 17) {
-      return MILLISECOND_FORMAT.parse(dateString);
+  public static Date stringToDate(String dateString) throws ParseException {
+    Resolution r;
+    try {
+      r = Resolution.lookupResolutionByLength(dateString.length());
+    } catch (IllegalArgumentException e) {
+      throw new ParseException("Input is not valid date string: " + dateString, 0);
     }
-    throw new ParseException("Input is not valid date string: " + dateString, 0);
+    return r.parseDate(dateString);
   }
   
   /**
@@ -173,7 +124,7 @@ public class DateTools {
    * @return the date with all values more precise than <code>resolution</code>
    *  set to 0 or 1
    */
-  public static synchronized Date round(Date date, Resolution resolution) {
+  public static Date round(Date date, Resolution resolution) {
     return new Date(round(date.getTime(), resolution));
   }
   
@@ -187,68 +138,87 @@ public class DateTools {
    * @return the date with all values more precise than <code>resolution</code>
    *  set to 0 or 1, expressed as milliseconds since January 1, 1970, 00:00:00 GMT
    */
-  public static synchronized long round(long time, Resolution resolution) {
-    calInstance.setTimeInMillis(time);
-    
-    if (resolution == Resolution.YEAR) {
-      calInstance.set(Calendar.MONTH, 0);
-      calInstance.set(Calendar.DAY_OF_MONTH, 1);
-      calInstance.set(Calendar.HOUR_OF_DAY, 0);
-      calInstance.set(Calendar.MINUTE, 0);
-      calInstance.set(Calendar.SECOND, 0);
-      calInstance.set(Calendar.MILLISECOND, 0);
-    } else if (resolution == Resolution.MONTH) {
-      calInstance.set(Calendar.DAY_OF_MONTH, 1);
-      calInstance.set(Calendar.HOUR_OF_DAY, 0);
-      calInstance.set(Calendar.MINUTE, 0);
-      calInstance.set(Calendar.SECOND, 0);
-      calInstance.set(Calendar.MILLISECOND, 0);
-    } else if (resolution == Resolution.DAY) {
-      calInstance.set(Calendar.HOUR_OF_DAY, 0);
-      calInstance.set(Calendar.MINUTE, 0);
-      calInstance.set(Calendar.SECOND, 0);
-      calInstance.set(Calendar.MILLISECOND, 0);
-    } else if (resolution == Resolution.HOUR) {
-      calInstance.set(Calendar.MINUTE, 0);
-      calInstance.set(Calendar.SECOND, 0);
-      calInstance.set(Calendar.MILLISECOND, 0);
-    } else if (resolution == Resolution.MINUTE) {
-      calInstance.set(Calendar.SECOND, 0);
-      calInstance.set(Calendar.MILLISECOND, 0);
-    } else if (resolution == Resolution.SECOND) {
-      calInstance.set(Calendar.MILLISECOND, 0);
-    } else if (resolution == Resolution.MILLISECOND) {
-      // don't cut off anything
-    } else {
-      throw new IllegalArgumentException("unknown resolution " + resolution);
-    }
-    return calInstance.getTimeInMillis();
+  public static long round(long time, Resolution resolution) {
+    return resolution.round(time);
   }
 
   /** Specifies the time granularity. */
   public static class Resolution {
-    
-    public static final Resolution YEAR = new Resolution("year");
-    public static final Resolution MONTH = new Resolution("month");
-    public static final Resolution DAY = new Resolution("day");
-    public static final Resolution HOUR = new Resolution("hour");
-    public static final Resolution MINUTE = new Resolution("minute");
-    public static final Resolution SECOND = new Resolution("second");
-    public static final Resolution MILLISECOND = new Resolution("millisecond");
+    private static final String FULLFMTPTN = "yyyyMMddHHmmssSSS";
+    public static final Resolution YEAR = new Resolution("year", 4);
+    public static final Resolution MONTH = new Resolution("month", 6);
+    public static final Resolution DAY = new Resolution("day", 8);
+    public static final Resolution HOUR = new Resolution("hour", 10);
+    public static final Resolution MINUTE = new Resolution("minute", 12);
+    public static final Resolution SECOND = new Resolution("second", 14);
+    public static final Resolution MILLISECOND = new Resolution("millisecond", 17);
 
-    private String resolution;
-
-    private Resolution() {
+    static Resolution lookupResolutionByLength(int len) {
+      switch(len) {
+        case 4: return YEAR;
+        case 6: return MONTH;
+        case 8: return DAY;
+        case 10: return HOUR;
+        case 12: return MINUTE;
+        case 14: return SECOND;
+        case 17: return MILLISECOND;
+        default:
+          throw new IllegalArgumentException("Invalid length: "+len);
+      }
     }
-    
-    private Resolution(String resolution) {
+
+    private final String resolution;
+    private final SimpleDateFormat format;//needs sync
+    private final Calendar calInstance = Calendar.getInstance(GMT);//needs sync
+
+    private Resolution(String resolution, int len) {
       this.resolution = resolution;
+      this.format = new SimpleDateFormat(FULLFMTPTN.substring(0,len));
+      this.format.setTimeZone(GMT);
     }
     
     public String toString() {
       return resolution;
     }
 
+    long round(long time) {
+      synchronized (calInstance) {
+        calInstance.setTimeInMillis(time);
+        //switch statement fall-through is deliberate
+        switch (format.toPattern().length()) {
+          case 4:
+            calInstance.set(Calendar.MONTH, 0);
+          case 6:
+            calInstance.set(Calendar.DAY_OF_MONTH, 1);
+          case 8:
+            calInstance.set(Calendar.HOUR_OF_DAY, 0);
+          case 10:
+            calInstance.set(Calendar.MINUTE, 0);
+          case 12:
+            calInstance.set(Calendar.SECOND, 0);
+          case 14:
+            calInstance.set(Calendar.MILLISECOND, 0);
+          case 17:
+            //do-nothing; millisecond full precision
+            break;
+          default:
+            throw new IllegalStateException("Unknown format length: "+format);
+        }
+        return calInstance.getTimeInMillis();
+      }
+    }
+
+    String formatDate(Date time) {
+      synchronized (format) {
+        return format.format(time);
+      }
+    }
+
+    Date parseDate(String dateString) throws ParseException {
+      synchronized (format) {
+        return format.parse(dateString);
+      }
+    }
   }
 
 }
