diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java index 47ebb6b2a..098f2b3b5 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java @@ -49,6 +49,7 @@ import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.util.GitDateParser; +import org.eclipse.jgit.util.SystemReader; import org.junit.Before; import org.junit.Test; @@ -68,7 +69,8 @@ public void setUp() throws Exception { @Test public void testGConeCommit() throws Exception { - Date expire = GitDateParser.parse("now", null); + Date expire = GitDateParser.parse("now", null, SystemReader + .getInstance().getLocale()); Properties res = git.gc().setExpire(expire).call(); assertTrue(res.size() == 7); } @@ -83,8 +85,11 @@ public void testGCmoreCommits() throws Exception { writeTrashFile("b.txt", "a couple of words for gc to pack more 2"); writeTrashFile("c.txt", "a couple of words for gc to pack more 3"); git.commit().setAll(true).setMessage("commit3").call(); - Properties res = git.gc().setExpire(GitDateParser.parse("now", null)) - .call(); + Properties res = git + .gc() + .setExpire( + GitDateParser.parse("now", null, SystemReader + .getInstance().getLocale())).call(); assertTrue(res.size() == 7); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserBadlyFormattedTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserBadlyFormattedTest.java index e0e99a14c..a6af3a514 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserBadlyFormattedTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserBadlyFormattedTest.java @@ -92,7 +92,8 @@ public void badlyFormattedWithExplicitRef() { Calendar ref = new GregorianCalendar(SystemReader.getInstance() .getTimeZone(), SystemReader.getInstance().getLocale()); try { - GitDateParser.parse(dateStr, ref); + GitDateParser.parse(dateStr, ref, SystemReader.getInstance() + .getLocale()); fail("The expected ParseException while parsing '" + dateStr + "' did not occur."); } catch (ParseException e) { @@ -103,7 +104,8 @@ public void badlyFormattedWithExplicitRef() { @Theory public void badlyFormattedWithoutRef() { try { - GitDateParser.parse(dateStr, null); + GitDateParser.parse(dateStr, null, SystemReader.getInstance() + .getLocale()); fail("The expected ParseException while parsing '" + dateStr + "' did not occur."); } catch (ParseException e) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserTest.java index 570f4999d..518ed53fd 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateParserTest.java @@ -72,7 +72,8 @@ public void yesterday() throws ParseException { GregorianCalendar cal = new GregorianCalendar(SystemReader .getInstance().getTimeZone(), SystemReader.getInstance() .getLocale()); - Date parse = GitDateParser.parse("yesterday", cal); + Date parse = GitDateParser.parse("yesterday", cal, SystemReader + .getInstance().getLocale()); cal.add(Calendar.DATE, -1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); @@ -87,7 +88,8 @@ public void never() throws ParseException { GregorianCalendar cal = new GregorianCalendar(SystemReader .getInstance().getTimeZone(), SystemReader.getInstance() .getLocale()); - Date parse = GitDateParser.parse("never", cal); + Date parse = GitDateParser.parse("never", cal, SystemReader + .getInstance().getLocale()); Assert.assertEquals(GitDateParser.NEVER, parse); parse = GitDateParser.parse("never", null); Assert.assertEquals(GitDateParser.NEVER, parse); @@ -104,7 +106,8 @@ public void now() throws ParseException { .getLocale()); cal.setTime(refDate); - Date parse = GitDateParser.parse("now", cal); + Date parse = GitDateParser.parse("now", cal, SystemReader.getInstance() + .getLocale()); Assert.assertEquals(refDate, parse); long t1 = SystemReader.getInstance().getCurrentTime(); parse = GitDateParser.parse("now", null); @@ -123,7 +126,8 @@ public void weeksAgo() throws ParseException { .getLocale()); cal.setTime(refDate); - Date parse = GitDateParser.parse("2 weeks ago", cal); + Date parse = GitDateParser.parse("2 weeks ago", cal, SystemReader + .getInstance().getLocale()); Assert.assertEquals(df.parse("2007-02-07 15:35:00 +0100"), parse); } @@ -138,7 +142,8 @@ public void daysAndWeeksAgo() throws ParseException { .getLocale()); cal.setTime(refDate); - Date parse = GitDateParser.parse("2 weeks ago", cal); + Date parse = GitDateParser.parse("2 weeks ago", cal, SystemReader.getInstance() + .getLocale()); Assert.assertEquals(df.parse("2007-02-07 15:35:00 +0100"), parse); parse = GitDateParser.parse("3 days 2 weeks ago", cal); Assert.assertEquals(df.parse("2007-02-04 15:35:00 +0100"), parse); @@ -151,7 +156,8 @@ public void iso() throws ParseException { String dateStr = "2007-02-21 15:35:00 +0100"; Date exp = SystemReader.getInstance() .getSimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } @@ -161,7 +167,8 @@ public void rfc() throws ParseException { Date exp = SystemReader.getInstance() .getSimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z") .parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } @@ -170,7 +177,8 @@ public void shortFmt() throws ParseException { String dateStr = "2007-02-21"; Date exp = SystemReader.getInstance().getSimpleDateFormat("yyyy-MM-dd") .parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } @@ -179,7 +187,8 @@ public void shortWithDots() throws ParseException { String dateStr = "2007.02.21"; Date exp = SystemReader.getInstance().getSimpleDateFormat("yyyy.MM.dd") .parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } @@ -188,7 +197,8 @@ public void shortWithSlash() throws ParseException { String dateStr = "02/21/2007"; Date exp = SystemReader.getInstance().getSimpleDateFormat("MM/dd/yyyy") .parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } @@ -197,7 +207,8 @@ public void shortWithDotsReverse() throws ParseException { String dateStr = "21.02.2007"; Date exp = SystemReader.getInstance().getSimpleDateFormat("dd.MM.yyyy") .parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } @@ -207,7 +218,8 @@ public void defaultFmt() throws ParseException { Date exp = SystemReader.getInstance() .getSimpleDateFormat("EEE MMM dd HH:mm:ss yyyy Z") .parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } @@ -216,7 +228,8 @@ public void local() throws ParseException { String dateStr = "Wed Feb 21 15:35:00 2007"; Date exp = SystemReader.getInstance() .getSimpleDateFormat("EEE MMM dd HH:mm:ss yyyy").parse(dateStr); - Date parse = GitDateParser.parse(dateStr, null); + Date parse = GitDateParser.parse(dateStr, null, SystemReader + .getInstance().getLocale()); Assert.assertEquals(exp, parse); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java index 9eaeaa8c1..e06ff65ee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java @@ -97,6 +97,7 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.GitDateParser; +import org.eclipse.jgit.util.SystemReader; /** * A garbage collector for git {@link FileRepository}. Instances of this class @@ -307,7 +308,8 @@ public void prune(Set objectsToKeep) throws IOException, ConfigConstants.CONFIG_KEY_PRUNEEXPIRE); if (pruneExpireStr == null) pruneExpireStr = PRUNE_EXPIRE_DEFAULT; - expire = GitDateParser.parse(pruneExpireStr, null); + expire = GitDateParser.parse(pruneExpireStr, null, SystemReader + .getInstance().getLocale()); expireAgeMillis = -1; } if (expire != null) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java index 8f4e491de..32859c9c5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java @@ -49,6 +49,7 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import org.eclipse.jgit.internal.JGitText; @@ -71,23 +72,40 @@ public class GitDateParser { // Since SimpleDateFormat instances are expensive to instantiate they should // be cached. Since they are also not threadsafe they are cached using // ThreadLocal. - private static ThreadLocal> formatCache = new ThreadLocal>() { - protected Map initialValue() { - return new HashMap(); + private static ThreadLocal>> formatCache = + new ThreadLocal>>() { + + protected Map> initialValue() { + return new HashMap>(); } }; - // Gets an instance of a SimpleDateFormat. If there is not already an - // appropriate instance in the (ThreadLocal) cache the create one and put in - // into the cache - private static SimpleDateFormat getDateFormat(ParseableSimpleDateFormat f) { - Map map = formatCache + // Gets an instance of a SimpleDateFormat for the specified locale. If there + // is not already an appropriate instance in the (ThreadLocal) cache then + // create one and put it into the cache. + private static SimpleDateFormat getDateFormat(ParseableSimpleDateFormat f, + Locale locale) { + Map> cache = formatCache .get(); + Map map = cache + .get(locale); + if (map == null) { + map = new HashMap(); + cache.put(locale, map); + return getNewSimpleDateFormat(f, locale, map); + } SimpleDateFormat dateFormat = map.get(f); if (dateFormat != null) return dateFormat; + SimpleDateFormat df = getNewSimpleDateFormat(f, locale, map); + return df; + } + + private static SimpleDateFormat getNewSimpleDateFormat( + ParseableSimpleDateFormat f, Locale locale, + Map map) { SimpleDateFormat df = SystemReader.getInstance().getSimpleDateFormat( - f.formatStr); + f.formatStr, locale); map.put(f, df); return df; } @@ -115,9 +133,9 @@ private ParseableSimpleDateFormat(String formatStr) { } /** - * Parses a string into a {@link Date}. Since this parser also supports - * relative formats (e.g. "yesterday") the caller can specify the reference - * date. These types of strings can be parsed: + * Parses a string into a {@link Date} using the default locale. Since this + * parser also supports relative formats (e.g. "yesterday") the caller can + * specify the reference date. These types of strings can be parsed: *
    *
  • "never"
  • *
  • "now"
  • @@ -151,6 +169,49 @@ private ParseableSimpleDateFormat(String formatStr) { */ public static Date parse(String dateStr, Calendar now) throws ParseException { + return parse(dateStr, now, Locale.getDefault()); + } + + /** + * Parses a string into a {@link Date} using the given locale. Since this + * parser also supports relative formats (e.g. "yesterday") the caller can + * specify the reference date. These types of strings can be parsed: + *
      + *
    • "never"
    • + *
    • "now"
    • + *
    • "yesterday"
    • + *
    • "(x) years|months|weeks|days|hours|minutes|seconds ago"
      + * Multiple specs can be combined like in "2 weeks 3 days ago". Instead of + * ' ' one can use '.' to seperate the words
    • + *
    • "yyyy-MM-dd HH:mm:ss Z" (ISO)
    • + *
    • "EEE, dd MMM yyyy HH:mm:ss Z" (RFC)
    • + *
    • "yyyy-MM-dd"
    • + *
    • "yyyy.MM.dd"
    • + *
    • "MM/dd/yyyy",
    • + *
    • "dd.MM.yyyy"
    • + *
    • "EEE MMM dd HH:mm:ss yyyy Z" (DEFAULT)
    • + *
    • "EEE MMM dd HH:mm:ss yyyy" (LOCAL)
    • + *
    + * + * @param dateStr + * the string to be parsed + * @param now + * the base date which is used for the calculation of relative + * formats. E.g. if baseDate is "25.8.2012" then parsing of the + * string "1 week ago" would result in a date corresponding to + * "18.8.2012". This is used when a JGit command calls this + * parser often but wants a consistent starting point for calls.
    + * If set to null then the current time will be used + * instead. + * @param locale + * locale to be used to parse the date string + * @return the parsed {@link Date} + * @throws ParseException + * if the given dateStr was not recognized + * @since 3.2 + */ + public static Date parse(String dateStr, Calendar now, Locale locale) + throws ParseException { dateStr = dateStr.trim(); Date ret; @@ -161,7 +222,7 @@ public static Date parse(String dateStr, Calendar now) return ret; for (ParseableSimpleDateFormat f : ParseableSimpleDateFormat.values()) { try { - return parse_simple(dateStr, f); + return parse_simple(dateStr, f, locale); } catch (ParseException e) { // simply proceed with the next parser } @@ -177,9 +238,10 @@ public static Date parse(String dateStr, Calendar now) } // tries to parse a string with the formats supported by SimpleDateFormat - private static Date parse_simple(String dateStr, ParseableSimpleDateFormat f) + private static Date parse_simple(String dateStr, + ParseableSimpleDateFormat f, Locale locale) throws ParseException { - SimpleDateFormat dateFormat = getDateFormat(f); + SimpleDateFormat dateFormat = getDateFormat(f, locale); dateFormat.setLenient(false); return dateFormat.parse(dateStr); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java index b6028610b..e73f100f9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java @@ -229,6 +229,21 @@ public SimpleDateFormat getSimpleDateFormat(String pattern) { return new SimpleDateFormat(pattern); } + /** + * Returns a simple date format instance as specified by the given pattern. + * + * @param pattern + * the pattern as defined in + * {@link SimpleDateFormat#SimpleDateFormat(String)} + * @param locale + * locale to be used for the {@code SimpleDateFormat} + * @return the simple date format + * @since 3.2 + */ + public SimpleDateFormat getSimpleDateFormat(String pattern, Locale locale) { + return new SimpleDateFormat(pattern, locale); + } + /** * Returns a date/time format instance for the given styles. *