From 38d76d8a30c48759dd7af86fab0f778364c0fbde Mon Sep 17 00:00:00 2001 From: Javid Khan Date: Tue, 28 Jul 2026 11:35:11 +0530 Subject: [PATCH 1/4] force gregorian calendar in ftp listing timestamp parsers --- .../parser/EnterpriseUnixFTPEntryParser.java | 3 ++- .../ftp/parser/FTPTimestampParserImpl.java | 4 +++ .../net/ftp/parser/MLSxEntryParser.java | 4 +-- .../EnterpriseUnixFTPEntryParserTest.java | 21 +++++++++++++++ .../parser/FTPTimestampParserImplTest.java | 26 +++++++++++++++++++ .../net/ftp/parser/MLSxEntryParserTest.java | 26 +++++++++++++++++++ 6 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java index c18fc6020..def415a36 100644 --- a/src/main/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java +++ b/src/main/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java @@ -18,6 +18,7 @@ package org.apache.commons.net.ftp.parser; import java.util.Calendar; +import java.util.GregorianCalendar; import org.apache.commons.net.ftp.FTPFile; @@ -105,7 +106,7 @@ public FTPFile parseFTPEntry(final String entry) { // intentionally do nothing } - final Calendar cal = Calendar.getInstance(); + final Calendar cal = new GregorianCalendar(); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MINUTE, 0); diff --git a/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java b/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java index 30a765bb5..cb4f2995f 100644 --- a/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java +++ b/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java @@ -23,6 +23,7 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.TimeZone; import org.apache.commons.net.ftp.Configurable; @@ -294,6 +295,7 @@ public Calendar parseTimestamp(final String timestampStr, final Calendar serverT final String year = Integer.toString(now.get(Calendar.YEAR)); final String timeStampStrPlusYear = timestampStr + " " + year; final SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy", recentDateFormat.getDateFormatSymbols()); + hackFormatter.setCalendar(new GregorianCalendar()); hackFormatter.setLenient(false); hackFormatter.setTimeZone(recentDateFormat.getTimeZone()); final ParsePosition pp = new ParsePosition(0); @@ -338,6 +340,7 @@ private void setDefaultDateFormat(final String format, final DateFormatSymbols d } else { defaultDateFormat = new SimpleDateFormat(format); } + defaultDateFormat.setCalendar(new GregorianCalendar()); defaultDateFormat.setLenient(false); } else { defaultDateFormat = null; @@ -363,6 +366,7 @@ private void setRecentDateFormat(final String format, final DateFormatSymbols df } else { recentDateFormat = new SimpleDateFormat(format); } + recentDateFormat.setCalendar(new GregorianCalendar()); recentDateFormat.setLenient(false); } else { recentDateFormat = null; diff --git a/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java index 7c2bc8b0f..5ffab350e 100644 --- a/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java +++ b/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java @@ -111,10 +111,10 @@ public static Calendar parseGMTdateTime(final String timestamp) { final SimpleDateFormat dateFormat; final boolean hasMillis; if (timestamp.contains(".")) { - dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS", Locale.ROOT); hasMillis = true; } else { - dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.ROOT); hasMillis = false; } final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT"); diff --git a/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java b/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java index 3ead102c9..dd2dad5d3 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java @@ -25,6 +25,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Calendar; +import java.util.Locale; import java.util.TimeZone; import org.apache.commons.net.ftp.FTPFile; @@ -156,6 +157,26 @@ void testParseFieldsOnFile() throws Exception { assertEquals(0, zDateTime.getSecond()); } + /** + * A numeric year in a listing must be read as a Gregorian year regardless of the JVM default locale. Under a Thai locale the base Calendar is a Buddhist + * calendar, which would otherwise store the timestamp 543 years out. + */ + @Test + void testAbsoluteYearWithNonGregorianDefaultLocale() { + final Locale defaultLocale = Locale.getDefault(); + try { + Locale.setDefault(new Locale("th", "TH")); + final FTPFile ftpFile = getParser().parseFTPEntry("-C--E-----FTP A QUA1I1 18128 41 Apr 1 2014 QUADTEST3"); + final TimeZone timeZone = TimeZone.getDefault(); + final ZonedDateTime zDateTime = ZonedDateTime.ofInstant(ftpFile.getTimestampInstant(), ZoneId.of(timeZone.getID())); + assertEquals(2014, zDateTime.getYear()); + assertEquals(Month.APRIL, zDateTime.getMonth()); + assertEquals(1, zDateTime.getDayOfMonth()); + } finally { + Locale.setDefault(defaultLocale); + } + } + @Override @Test void testRecentPrecision() { diff --git a/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java b/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java index e7662ed4b..42091f8aa 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java @@ -271,6 +271,32 @@ void testParser() throws ParseException { } } + /** + * A numeric year from a server listing must be read as a Gregorian year regardless of the JVM default locale. Under a Thai locale the default + * SimpleDateFormat calendar is a Buddhist calendar, which would otherwise shift the parsed instant by 543 years. + */ + @Test + void testParseTimestampWithNonGregorianDefaultLocale() throws ParseException { + final Locale defaultLocale = Locale.getDefault(); + try { + Locale.setDefault(new Locale("th", "TH")); + final FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); + final FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX); + config.setDefaultDateFormatStr("yyyy-MM-dd HH:mm"); + config.setRecentDateFormatStr("MMM d HH:mm"); + config.setServerLanguageCode("en"); + config.setServerTimeZoneId("GMT"); + parser.configure(config); + final Calendar parsed = parser.parseTimestamp("2010-03-13 22:45", new GregorianCalendar()); + final GregorianCalendar expected = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); + expected.clear(); + expected.set(2010, Calendar.MARCH, 13, 22, 45, 0); + assertEquals(expected.getTimeInMillis(), parsed.getTimeInMillis()); + } finally { + Locale.setDefault(defaultLocale); + } + } + @Test void testParseShortFutureDates1() throws Exception { final GregorianCalendar now = new GregorianCalendar(2001, Calendar.MAY, 30, 12, 0); diff --git a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java index 325d108a1..2e013f842 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java @@ -16,6 +16,13 @@ */ package org.apache.commons.net.ftp.parser; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; import org.junit.jupiter.api.Test; @@ -68,6 +75,25 @@ protected FTPFile nullFileOrNullDate(final FTPFile f) { return f; } + /** + * The RFC 3659 time stamp is a numeric Gregorian date. Parsing it must not depend on the JVM default locale's calendar, which for e.g. a Thai locale is a + * Buddhist calendar that would read the year 543 years out. + */ + @Test + void testParseGMTdateTimeWithNonGregorianDefaultLocale() { + final Locale defaultLocale = Locale.getDefault(); + try { + Locale.setDefault(new Locale("th", "TH")); + final Calendar parsed = MLSxEntryParser.parseGMTdateTime("20100313224553"); + final GregorianCalendar expected = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); + expected.clear(); + expected.set(2010, Calendar.MARCH, 13, 22, 45, 53); + assertEquals(expected.getTimeInMillis(), parsed.getTimeInMillis()); + } finally { + Locale.setDefault(defaultLocale); + } + } + @Override @Test void testDefaultPrecision() { From ce157b3553c36926a954405e32d9546e419b7066 Mon Sep 17 00:00:00 2001 From: Javid Khan Date: Wed, 29 Jul 2026 12:20:49 +0530 Subject: [PATCH 2/4] use junit pioneer for locale tests and derive appended year from gregorian calendar --- pom.xml | 5 ++ .../ftp/parser/FTPTimestampParserImpl.java | 6 +- .../EnterpriseUnixFTPEntryParserTest.java | 21 +++---- .../parser/FTPTimestampParserImplTest.java | 60 +++++++++++++------ .../net/ftp/parser/MLSxEntryParserTest.java | 18 +++--- 5 files changed, 67 insertions(+), 43 deletions(-) diff --git a/pom.xml b/pom.xml index b30b1cff0..531aacab0 100644 --- a/pom.xml +++ b/pom.xml @@ -119,6 +119,11 @@ Supported protocols include Echo, Finger, FTP, NNTP, NTP, POP3(S), SMTP(S), Teln junit-jupiter-params test + + org.junit-pioneer + junit-pioneer + test + org.apache.ftpserver ftpserver-core diff --git a/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java b/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java index cb4f2995f..9976ff338 100644 --- a/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java +++ b/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java @@ -292,7 +292,11 @@ public Calendar parseTimestamp(final String timestampStr, final Calendar serverT // all instances of short dates which are +- 6 months from current date. // TODO this won't always work for systems that use short dates +0/-12months // e.g. if today is Jan 1 2001 and the short date is Feb 29 - final String year = Integer.toString(now.get(Calendar.YEAR)); + // now is a clone of the caller's serverTime, which under some default locales (e.g. a Thai Buddhist calendar) is not Gregorian, so read the year + // through a Gregorian calendar at the same instant to keep the appended year Gregorian rather than 543 years out. + final GregorianCalendar gregorianNow = new GregorianCalendar(now.getTimeZone()); + gregorianNow.setTimeInMillis(now.getTimeInMillis()); + final String year = Integer.toString(gregorianNow.get(Calendar.YEAR)); final String timeStampStrPlusYear = timestampStr + " " + year; final SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy", recentDateFormat.getDateFormatSymbols()); hackFormatter.setCalendar(new GregorianCalendar()); diff --git a/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java b/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java index dd2dad5d3..d1674ddad 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java @@ -25,12 +25,12 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Calendar; -import java.util.Locale; import java.util.TimeZone; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.DefaultLocale; /** * Tests the EnterpriseUnixFTPEntryParser @@ -162,19 +162,14 @@ void testParseFieldsOnFile() throws Exception { * calendar, which would otherwise store the timestamp 543 years out. */ @Test + @DefaultLocale(language = "th", country = "TH") void testAbsoluteYearWithNonGregorianDefaultLocale() { - final Locale defaultLocale = Locale.getDefault(); - try { - Locale.setDefault(new Locale("th", "TH")); - final FTPFile ftpFile = getParser().parseFTPEntry("-C--E-----FTP A QUA1I1 18128 41 Apr 1 2014 QUADTEST3"); - final TimeZone timeZone = TimeZone.getDefault(); - final ZonedDateTime zDateTime = ZonedDateTime.ofInstant(ftpFile.getTimestampInstant(), ZoneId.of(timeZone.getID())); - assertEquals(2014, zDateTime.getYear()); - assertEquals(Month.APRIL, zDateTime.getMonth()); - assertEquals(1, zDateTime.getDayOfMonth()); - } finally { - Locale.setDefault(defaultLocale); - } + final FTPFile ftpFile = getParser().parseFTPEntry("-C--E-----FTP A QUA1I1 18128 41 Apr 1 2014 QUADTEST3"); + final TimeZone timeZone = TimeZone.getDefault(); + final ZonedDateTime zDateTime = ZonedDateTime.ofInstant(ftpFile.getTimestampInstant(), ZoneId.of(timeZone.getID())); + assertEquals(2014, zDateTime.getYear()); + assertEquals(Month.APRIL, zDateTime.getMonth()); + assertEquals(1, zDateTime.getDayOfMonth()); } @Override diff --git a/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java b/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java index 42091f8aa..55a5618a6 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java @@ -32,6 +32,7 @@ import org.apache.commons.net.ftp.FTPClientConfig; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.DefaultLocale; /** * Test the FTPTimestampParser class. @@ -276,25 +277,48 @@ void testParser() throws ParseException { * SimpleDateFormat calendar is a Buddhist calendar, which would otherwise shift the parsed instant by 543 years. */ @Test + @DefaultLocale(language = "th", country = "TH") void testParseTimestampWithNonGregorianDefaultLocale() throws ParseException { - final Locale defaultLocale = Locale.getDefault(); - try { - Locale.setDefault(new Locale("th", "TH")); - final FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); - final FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX); - config.setDefaultDateFormatStr("yyyy-MM-dd HH:mm"); - config.setRecentDateFormatStr("MMM d HH:mm"); - config.setServerLanguageCode("en"); - config.setServerTimeZoneId("GMT"); - parser.configure(config); - final Calendar parsed = parser.parseTimestamp("2010-03-13 22:45", new GregorianCalendar()); - final GregorianCalendar expected = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); - expected.clear(); - expected.set(2010, Calendar.MARCH, 13, 22, 45, 0); - assertEquals(expected.getTimeInMillis(), parsed.getTimeInMillis()); - } finally { - Locale.setDefault(defaultLocale); - } + final FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); + final FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX); + config.setDefaultDateFormatStr("yyyy-MM-dd HH:mm"); + config.setRecentDateFormatStr("MMM d HH:mm"); + config.setServerLanguageCode("en"); + config.setServerTimeZoneId("GMT"); + parser.configure(config); + final Calendar parsed = parser.parseTimestamp("2010-03-13 22:45", new GregorianCalendar()); + final GregorianCalendar expected = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); + expected.clear(); + expected.set(2010, Calendar.MARCH, 13, 22, 45, 0); + assertEquals(expected.getTimeInMillis(), parsed.getTimeInMillis()); + } + + /** + * A recent (short) date carries no year, so the parser appends the year taken from the supplied server time. When a caller builds that server time via + * {@link Calendar#getInstance()} under a Thai default locale it is a Buddhist calendar, so the appended year must be read through a Gregorian calendar or + * the parsed instant lands 543 years out. + */ + @Test + @DefaultLocale(language = "th", country = "TH") + void testParseRecentTimestampWithNonGregorianDefaultLocale() throws ParseException { + final FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); + final FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX); + config.setDefaultDateFormatStr("yyyy-MM-dd HH:mm"); + config.setRecentDateFormatStr("MMM d HH:mm"); + config.setServerLanguageCode("en"); + config.setServerTimeZoneId("GMT"); + parser.configure(config); + // Calendar.getInstance() under a Thai default locale is a Buddhist calendar, mirroring how a caller builds the server time. + final Calendar serverTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + final GregorianCalendar serverInstant = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); + serverInstant.clear(); + serverInstant.set(2010, Calendar.JUNE, 1, 0, 0, 0); + serverTime.setTimeInMillis(serverInstant.getTimeInMillis()); + final Calendar parsed = parser.parseTimestamp("Mar 13 22:45", serverTime); + final GregorianCalendar expected = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); + expected.clear(); + expected.set(2010, Calendar.MARCH, 13, 22, 45, 0); + assertEquals(expected.getTimeInMillis(), parsed.getTimeInMillis()); } @Test diff --git a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java index 2e013f842..1905af076 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java @@ -26,6 +26,7 @@ import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.DefaultLocale; /** */ @@ -80,18 +81,13 @@ protected FTPFile nullFileOrNullDate(final FTPFile f) { * Buddhist calendar that would read the year 543 years out. */ @Test + @DefaultLocale(language = "th", country = "TH") void testParseGMTdateTimeWithNonGregorianDefaultLocale() { - final Locale defaultLocale = Locale.getDefault(); - try { - Locale.setDefault(new Locale("th", "TH")); - final Calendar parsed = MLSxEntryParser.parseGMTdateTime("20100313224553"); - final GregorianCalendar expected = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); - expected.clear(); - expected.set(2010, Calendar.MARCH, 13, 22, 45, 53); - assertEquals(expected.getTimeInMillis(), parsed.getTimeInMillis()); - } finally { - Locale.setDefault(defaultLocale); - } + final Calendar parsed = MLSxEntryParser.parseGMTdateTime("20100313224553"); + final GregorianCalendar expected = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.ROOT); + expected.clear(); + expected.set(2010, Calendar.MARCH, 13, 22, 45, 53); + assertEquals(expected.getTimeInMillis(), parsed.getTimeInMillis()); } @Override From ec8574ec366b33ace549f4dadbb154955d8fd7d9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 29 Jul 2026 10:04:08 -0400 Subject: [PATCH 3/4] No latin needed. Updated comment for clarity regarding RFC 3659 timestamp parsing with non-Gregorian locales. --- .../apache/commons/net/ftp/parser/MLSxEntryParserTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java index 1905af076..9f5368ddb 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java @@ -77,8 +77,8 @@ protected FTPFile nullFileOrNullDate(final FTPFile f) { } /** - * The RFC 3659 time stamp is a numeric Gregorian date. Parsing it must not depend on the JVM default locale's calendar, which for e.g. a Thai locale is a - * Buddhist calendar that would read the year 543 years out. + * The RFC 3659 time stamp is a numeric Gregorian date. Parsing it must not depend on the JVM default locale's calendar, which, for example, + * a Thai locale is a Buddhist calendar that would read the year 543 years out. */ @Test @DefaultLocale(language = "th", country = "TH") From ea222f37f3f1cf0ecb9ed6be387e820e69991ba7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 29 Jul 2026 10:08:54 -0400 Subject: [PATCH 4/4] Clarify RFC 3659 timestamp parsing in test Update test comment to clarify RFC 3659 timestamp parsing. --- .../org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java index 9f5368ddb..b99b619b3 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/MLSxEntryParserTest.java @@ -77,7 +77,7 @@ protected FTPFile nullFileOrNullDate(final FTPFile f) { } /** - * The RFC 3659 time stamp is a numeric Gregorian date. Parsing it must not depend on the JVM default locale's calendar, which, for example, + * The RFC 3659 time stamp is a numeric Gregorian date. Parsing it must not depend on the JVM default locale's calendar, which, for example, * a Thai locale is a Buddhist calendar that would read the year 543 years out. */ @Test