summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--htroot/CrawlResults.java14
-rw-r--r--htroot/IndexCreateQueues_p.java18
-rw-r--r--source/net/yacy/cora/document/feed/RSSMessage.java11
-rw-r--r--source/net/yacy/cora/protocol/HeaderFramework.java66
-rw-r--r--test/java/net/yacy/cora/protocol/HeaderFrameworkTest.java51
5 files changed, 144 insertions, 16 deletions
diff --git a/htroot/CrawlResults.java b/htroot/CrawlResults.java
index ef9c2312b..3429ac31b 100644
--- a/htroot/CrawlResults.java
+++ b/htroot/CrawlResults.java
@@ -24,7 +24,8 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-import java.text.SimpleDateFormat;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
@@ -34,6 +35,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import net.yacy.cora.date.GenericFormatter;
import net.yacy.cora.document.encoding.ASCII;
import net.yacy.cora.document.encoding.UTF8;
import net.yacy.cora.document.id.Punycode.PunycodeException;
@@ -350,11 +352,17 @@ public class CrawlResults {
return prop;
}
- private static SimpleDateFormat dayFormatter = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+ private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter
+ .ofPattern("uuuu/MM/dd", Locale.US).withZone(ZoneId.systemDefault());
+
+ /**
+ * @param date a date to render as a String
+ * @return the date formatted using the DAY_FORMATTER pattern.
+ */
private static String daydate(final Date date) {
if (date == null) {
return "";
}
- return dayFormatter.format(date);
+ return GenericFormatter.formatSafely(date.toInstant(), DAY_FORMATTER);
}
}
diff --git a/htroot/IndexCreateQueues_p.java b/htroot/IndexCreateQueues_p.java
index 393889daf..96c135067 100644
--- a/htroot/IndexCreateQueues_p.java
+++ b/htroot/IndexCreateQueues_p.java
@@ -1,6 +1,7 @@
import java.net.MalformedURLException;
-import java.text.SimpleDateFormat;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
@@ -12,6 +13,7 @@ import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import net.yacy.cora.date.GenericFormatter;
import net.yacy.cora.document.encoding.ASCII;
import net.yacy.cora.document.id.DigestURL;
import net.yacy.cora.protocol.Domains;
@@ -28,10 +30,18 @@ import net.yacy.server.serverSwitch;
public class IndexCreateQueues_p {
- private static SimpleDateFormat dayFormatter = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+ private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter
+ .ofPattern("uuuu/MM/dd", Locale.US).withZone(ZoneId.systemDefault());
+
+ /**
+ * @param date a date to render as a String
+ * @return the date formatted using the DAY_FORMATTER pattern.
+ */
private static String daydate(final Date date) {
- if (date == null) return "";
- return dayFormatter.format(date);
+ if (date == null) {
+ return "";
+ }
+ return GenericFormatter.formatSafely(date.toInstant(), DAY_FORMATTER);
}
private static final int INVALID = 0;
diff --git a/source/net/yacy/cora/document/feed/RSSMessage.java b/source/net/yacy/cora/document/feed/RSSMessage.java
index a12768a24..8906d103b 100644
--- a/source/net/yacy/cora/document/feed/RSSMessage.java
+++ b/source/net/yacy/cora/document/feed/RSSMessage.java
@@ -25,6 +25,7 @@
package net.yacy.cora.document.feed;
import java.text.ParseException;
+import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -156,7 +157,7 @@ public class RSSMessage implements Hit, Comparable<RSSMessage>, Comparator<RSSMe
if (title.length() > 0) this.map.put(Token.title.name(), title);
if (description.length() > 0) this.map.put(Token.description.name(), description);
if (link.length() > 0) this.map.put(Token.link.name(), link);
- this.map.put(Token.pubDate.name(), HeaderFramework.FORMAT_RFC1123.format(new Date()));
+ this.map.put(Token.pubDate.name(), HeaderFramework.formatNowRFC1123());
this.map.put(Token.guid.name(), artificialGuidPrefix + Integer.toHexString((title + description + link).hashCode()));
}
@@ -165,7 +166,7 @@ public class RSSMessage implements Hit, Comparable<RSSMessage>, Comparator<RSSMe
if (title.length() > 0) this.map.put(Token.title.name(), title);
if (description.length() > 0) this.map.put(Token.description.name(), description);
this.map.put(Token.link.name(), link.toNormalform(true));
- this.map.put(Token.pubDate.name(), HeaderFramework.FORMAT_RFC1123.format(new Date()));
+ this.map.put(Token.pubDate.name(), HeaderFramework.formatNowRFC1123());
if (guid.length() > 0) {
this.map.put(Token.guid.name(), guid);
}
@@ -261,8 +262,8 @@ public class RSSMessage implements Hit, Comparable<RSSMessage>, Comparator<RSSMe
if (!dateString.isEmpty()) { // skip parse exception on empty string
Date date;
try {
- date = HeaderFramework.FORMAT_RFC1123.parse(dateString);
- } catch (final ParseException e) {
+ date = Date.from(ZonedDateTime.parse(dateString, HeaderFramework.RFC1123_FORMATTER).toInstant());
+ } catch (final RuntimeException e) {
try {
date = GenericFormatter.SHORT_SECOND_FORMATTER.parse(dateString, 0).getTime();
} catch (final ParseException e1) {
@@ -401,7 +402,7 @@ public class RSSMessage implements Hit, Comparable<RSSMessage>, Comparator<RSSMe
@Override
public void setPubDate(final Date pubdate) {
- setValue(Token.pubDate, HeaderFramework.FORMAT_RFC1123.format(pubdate));
+ setValue(Token.pubDate, HeaderFramework.formatNowRFC1123());
}
@Override
diff --git a/source/net/yacy/cora/protocol/HeaderFramework.java b/source/net/yacy/cora/protocol/HeaderFramework.java
index 3595cc933..0eeb3ddf2 100644
--- a/source/net/yacy/cora/protocol/HeaderFramework.java
+++ b/source/net/yacy/cora/protocol/HeaderFramework.java
@@ -26,6 +26,10 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
@@ -230,10 +234,33 @@ public class HeaderFramework extends TreeMap<String, String> implements Map<Stri
/** Date formatter/parser for standard compliant HTTP header dates (RFC 1123) */
private static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss Z"; // with numeric time zone indicator as defined in RFC5322
private static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
- public static final SimpleDateFormat FORMAT_RFC1123 = new SimpleDateFormat(PATTERN_RFC1123, Locale.US);
- public static final SimpleDateFormat FORMAT_RFC1036 = new SimpleDateFormat(PATTERN_RFC1036, Locale.US);
+ private static final SimpleDateFormat FORMAT_RFC1123 = new SimpleDateFormat(PATTERN_RFC1123, Locale.US);
private static final TimeZone TZ_GMT = TimeZone.getTimeZone("GMT");
private static final Calendar CAL_GMT = Calendar.getInstance(TZ_GMT, Locale.US);
+
+ /**
+ * A thread-safe date formatter using the
+ * {@link HeaderFramework#PATTERN_RFC1123} pattern with the US locale on the UTC
+ * time zone.
+ */
+ public static final DateTimeFormatter RFC1123_FORMATTER = DateTimeFormatter
+ .ofPattern(PATTERN_RFC1123.replace("yyyy", "uuuu")).withLocale(Locale.US).withZone(ZoneOffset.UTC);
+
+ /**
+ * @return a new SimpleDateFormat instance using the
+ * {@link HeaderFramework#PATTERN_RFC1123} pattern with the US locale.
+ */
+ public static SimpleDateFormat newRfc1123Format() {
+ return new SimpleDateFormat(HeaderFramework.PATTERN_RFC1123, Locale.US);
+ }
+
+ /**
+ * @return a new SimpleDateFormat instance using the
+ * {@link HeaderFramework#PATTERN_RFC1036} pattern with the US locale.
+ */
+ public static SimpleDateFormat newRfc1036Format() {
+ return new SimpleDateFormat(HeaderFramework.PATTERN_RFC1036, Locale.US);
+ }
/**
* RFC 2616 requires that HTTP clients are able to parse all 3 different
@@ -241,9 +268,9 @@ public class HeaderFramework extends TreeMap<String, String> implements Map<Stri
*/
private static final SimpleDateFormat[] FORMATS_HTTP = new SimpleDateFormat[] {
// RFC 1123/822 (Standard) "Mon, 12 Nov 2007 10:11:12 GMT"
- FORMAT_RFC1123,
+ newRfc1123Format(),
// RFC 1036/850 (old) "Monday, 12-Nov-07 10:11:12 GMT"
- FORMAT_RFC1036,
+ newRfc1036Format(),
// ANSI C asctime() "Mon Nov 12 10:11:12 2007"
GenericFormatter.newAnsicFormat(),
};
@@ -265,6 +292,34 @@ public class HeaderFramework extends TreeMap<String, String> implements Map<Stri
return s;
}
}
+
+ /**
+ * @param epochMilli
+ * a time value as the number of milliseconds from Epoch
+ * (1970-01-01T00:00:00Z)
+ * @return the time formatted using the {@link HeaderFramework#PATTERN_RFC1123}
+ * pattern.
+ */
+ public static final String formatRFC1123(final long epochMilli) {
+ try {
+ /* Prefer first using the thread-safe DateTimeFormatter shared instance */
+ return RFC1123_FORMATTER.format(Instant.ofEpochMilli(epochMilli));
+ } catch (final DateTimeException e) {
+ /*
+ * This should not happen, but rather than failing we prefer here to use
+ * formatting function using the synchronized SimpleDateFormat
+ */
+ return formatRFC1123(new Date(epochMilli));
+ }
+ }
+
+ /**
+ * @return the current time formatted using the
+ * {@link HeaderFramework#PATTERN_RFC1123} pattern.
+ */
+ public static final String formatNowRFC1123() {
+ return formatRFC1123(System.currentTimeMillis());
+ }
/** Initialization of static formats */
static {
@@ -277,6 +332,9 @@ public class HeaderFramework extends TreeMap<String, String> implements Map<Stri
format.setTimeZone(TZ_GMT);
format.set2DigitYearStart(CAL_GMT.getTime());
}
+
+ FORMAT_RFC1123.setTimeZone(TZ_GMT);
+ FORMAT_RFC1123.set2DigitYearStart(CAL_GMT.getTime());
}
/**
diff --git a/test/java/net/yacy/cora/protocol/HeaderFrameworkTest.java b/test/java/net/yacy/cora/protocol/HeaderFrameworkTest.java
index 71d013698..971dc57ad 100644
--- a/test/java/net/yacy/cora/protocol/HeaderFrameworkTest.java
+++ b/test/java/net/yacy/cora/protocol/HeaderFrameworkTest.java
@@ -1,6 +1,29 @@
+// HeaderFrameworkTest.java
+// Copyright 2006-2018 by theli, f1ori, Michael Peter Christen; mc@yacy.net, reger; reger18@arcor.de, luccioman; https://github.com/luccioman
+//
+// This is a part of YaCy, a peer-to-peer based web search engine
+//
+// LICENSE
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
package net.yacy.cora.protocol;
+import java.time.Instant;
import java.util.Date;
+
import junit.framework.TestCase;
import org.junit.Test;
@@ -18,6 +41,22 @@ public class HeaderFrameworkTest extends TestCase {
// Print Result
System.out.println("testParseHTTPDate: " + parsedDate.toString());
+
+ parsedDate = HeaderFramework.parseHTTPDate("Monday, 12-Nov-07 10:11:12 GMT");
+
+ // returned date must not be null
+ assertNotNull(parsedDate);
+
+ // Print Result
+ System.out.println("testParseHTTPDate: " + parsedDate.toString());
+
+ parsedDate = HeaderFramework.parseHTTPDate("Mon Nov 12 10:11:12 2007");
+
+ // returned date must not be null
+ assertNotNull(parsedDate);
+
+ // Print Result
+ System.out.println("testParseHTTPDate: " + parsedDate.toString());
}
/**
@@ -31,4 +70,16 @@ public class HeaderFrameworkTest extends TestCase {
assertEquals("utf-8", HeaderFramework.getCharacterEncoding("Text/HTML;Charset=\"utf-8\""));
assertEquals("utf-8", HeaderFramework.getCharacterEncoding("text/html; charset=\"utf-8\""));
}
+
+ /**
+ * Unit test for date formatting with RFC 1123 format
+ */
+ @Test
+ public void testFormatRfc1123() {
+ assertEquals("", HeaderFramework.formatRFC1123(null));
+
+ final Instant time = Instant.parse("2018-06-29T13:04:55.00Z");
+ assertEquals("Fri, 29 Jun 2018 13:04:55 +0000", HeaderFramework.formatRFC1123(time.toEpochMilli()));
+ assertEquals("Fri, 29 Jun 2018 13:04:55 +0000", HeaderFramework.formatRFC1123(Date.from(time)));
+ }
}