From 4347903d1d7719cee4e666507fd1d7ef5be2584e Mon Sep 17 00:00:00 2001
From: Brad Hall
Date: Thu, 11 Apr 2024 13:13:22 -0400
Subject: [PATCH 1/3] Changed to use OffsetDateTime and DateTimeFormatter for
the date time parsing
---
README.md | 4 +-
pom.xml | 2 +-
.../AbstractSitemapGeneratorOptions.java | 3 +-
.../AbstractSitemapUrlOptions.java | 8 +-
.../GoogleLinkSitemapGenerator.java | 4 +-
.../GoogleNewsSitemapUrl.java | 24 +-
.../GoogleVideoSitemapUrl.java | 10 +-
.../redfin/sitemapgenerator/ISitemapUrl.java | 4 +-
.../sitemapgenerator/SitemapGenerator.java | 6 +-
.../SitemapIndexGenerator.java | 24 +-
.../sitemapgenerator/SitemapIndexUrl.java | 12 +-
.../sitemapgenerator/W3CDateFormat.java | 323 +++++++++---------
.../sitemapgenerator/WebSitemapUrl.java | 10 +-
.../GoogleImageSitemapUrlTest.java | 4 +-
.../GoogleLinkSitemapUrlTest.java | 1 -
.../GoogleNewsSitemapUrlTest.java | 23 +-
.../GoogleVideoSitemapUrlTest.java | 10 +-
.../SitemapGeneratorTest.java | 17 +-
.../SitemapIndexGeneratorTest.java | 15 +-
.../com/redfin/sitemapgenerator/TestUtil.java | 6 +-
.../sitemapgenerator/TutorialExampleTest.java | 10 +-
.../sitemapgenerator/W3CDateFormatTest.java | 61 ++--
22 files changed, 290 insertions(+), 291 deletions(-)
diff --git a/README.md b/README.md
index 7006b1b..f5321ca 100644
--- a/README.md
+++ b/README.md
@@ -74,8 +74,8 @@ One important configuration option for the sitemap generator is the date format.
```java
// Use DAY pattern (2009-02-07), Greenwich Mean Time timezone
-W3CDateFormat dateFormat = new W3CDateFormat(Pattern.DAY);
-dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+ZoneId zoneId = TimeZone.getTimeZone("GMT").toZoneId();
+W3CDateFormat dateFormat = W3CDateFormat.DAY.withZone(zoneId);
WebSitemapGenerator wsg = WebSitemapGenerator.builder("https://www.example.com", myDir)
.dateFormat(dateFormat).build(); // actually use the configured dateFormat
wsg.addUrl("https://www.example.com/index.html");
diff --git a/pom.xml b/pom.xml
index 5c4e977..9844291 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
io.gdcc
sitemapgen4j
jar
- 2.1.3-SNAPSHOT
+ 2.2.0-SNAPSHOT
SitemapGen4J
https://github.com/gdcc/sitemapgen4j/
diff --git a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java
index c5d915f..8479ac3 100644
--- a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java
+++ b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java
@@ -2,6 +2,7 @@
import java.io.File;
import java.net.URL;
+import java.time.format.DateTimeFormatter;
// that weird thing with generics is so sub-classed objects will return themselves
// It makes sense, I swear! https://madbean.com/2004/mb2004-3/
@@ -55,7 +56,7 @@ public T allowMultipleSitemaps(boolean allowMultipleSitemaps) {
this.allowMultipleSitemaps = allowMultipleSitemaps;
return getThis();
}
- /** The date formatter, typically configured with a {@link W3CDateFormat.Pattern} and/or a time zone */
+ /** The date formatter, typically configured with a {@link DateTimeFormatter} and/or a time zone */
public T dateFormat(W3CDateFormat dateFormat) {
this.dateFormat = dateFormat;
return getThis();
diff --git a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java
index 44f35ae..56eaf01 100644
--- a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java
+++ b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java
@@ -3,13 +3,13 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
-import java.util.Date;
+import java.time.OffsetDateTime;
/** Container for optional URL parameters */
//that weird thing with generics is so sub-classed objects will return themselves
//It makes sense, I swear! https://madbean.com/2004/mb2004-3/
abstract class AbstractSitemapUrlOptions> {
- Date lastMod;
+ OffsetDateTime lastMod;
ChangeFreq changeFreq;
Double priority;
URL url;
@@ -31,7 +31,7 @@ abstract class AbstractSitemapUrlOptions {
- private final Date publicationDate;
+ private final OffsetDateTime publicationDate;
private String keywords;
private String genres;
private final String title;
private final GoogleNewsPublication publication;
/** Specifies a URL and publication date (which is mandatory for Google News) */
- public Options(String url, Date publicationDate, String title, GoogleNewsPublication publication) throws MalformedURLException {
+ public Options(String url, OffsetDateTime publicationDate, String title, GoogleNewsPublication publication) throws MalformedURLException {
this(new URL(url), publicationDate, title, publication);
}
- public Options(String url, Date publicationDate, String title, String name, String language) throws MalformedURLException {
+ public Options(String url, OffsetDateTime publicationDate, String title, String name, String language) throws MalformedURLException {
this(new URL(url), publicationDate, title, new GoogleNewsPublication(name, language));
}
- public Options(URL url, Date publicationDate, String title, String name, String language) {
+ public Options(URL url, OffsetDateTime publicationDate, String title, String name, String language) {
this(url, publicationDate, title, new GoogleNewsPublication(name, language));
}
/** Specifies a URL and publication date (which is mandatory for Google News) */
- public Options(URL url, Date publicationDate, String title, GoogleNewsPublication publication) {
+ public Options(URL url, OffsetDateTime publicationDate, String title, GoogleNewsPublication publication) {
super(url, GoogleNewsSitemapUrl.class);
if (publicationDate == null) throw new NullPointerException("publicationDate must not be null");
this.publicationDate = publicationDate;
@@ -101,22 +101,22 @@ public Options genres(String... genres) {
}
/** Specifies a URL and publication date, title and publication (which are mandatory for Google News) */
- public GoogleNewsSitemapUrl(URL url, Date publicationDate, String title, String name, String language) {
+ public GoogleNewsSitemapUrl(URL url, OffsetDateTime publicationDate, String title, String name, String language) {
this(new Options(url, publicationDate, title, name, language));
}
/** Specifies a URL and publication date, title and publication (which are mandatory for Google News) */
- public GoogleNewsSitemapUrl(URL url, Date publicationDate, String title, GoogleNewsPublication publication) {
+ public GoogleNewsSitemapUrl(URL url, OffsetDateTime publicationDate, String title, GoogleNewsPublication publication) {
this(new Options(url, publicationDate, title, publication));
}
/** Specifies a URL and publication date, title and publication (which are mandatory for Google News) */
- public GoogleNewsSitemapUrl(String url, Date publicationDate, String title, String name, String language) throws MalformedURLException {
+ public GoogleNewsSitemapUrl(String url, OffsetDateTime publicationDate, String title, String name, String language) throws MalformedURLException {
this(new Options(url, publicationDate, title, name, language));
}
/** Specifies a URL and publication date, title and publication (which are mandatory for Google News) */
- public GoogleNewsSitemapUrl(String url, Date publicationDate, String title, GoogleNewsPublication publication) throws MalformedURLException {
+ public GoogleNewsSitemapUrl(String url, OffsetDateTime publicationDate, String title, GoogleNewsPublication publication) throws MalformedURLException {
this(new Options(url, publicationDate, title, publication));
}
@@ -131,7 +131,7 @@ public GoogleNewsSitemapUrl(Options options) {
}
/** Retrieves the publication date */
- public Date getPublicationDate() {
+ public OffsetDateTime getPublicationDate() {
return publicationDate;
}
diff --git a/src/main/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrl.java b/src/main/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrl.java
index 6180b8c..3ce9f9c 100644
--- a/src/main/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrl.java
+++ b/src/main/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrl.java
@@ -1,9 +1,9 @@
package com.redfin.sitemapgenerator;
import java.net.URL;
+import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
/** One configurable Google Video Search URL. To configure, use {@link Options}
@@ -21,7 +21,7 @@ public class GoogleVideoSitemapUrl extends WebSitemapUrl {
private final String description;
private final Double rating;
private final Integer viewCount;
- private final Date publicationDate;
+ private final OffsetDateTime publicationDate;
private final List tags;
private final String category;
// TODO can there be multiple categories?
@@ -40,7 +40,7 @@ public static class Options extends AbstractSitemapUrlOptions tags;
private String category;
// TODO can there be multiple categories?
@@ -137,7 +137,7 @@ public Options viewCount(int viewCount) {
}
/** The date the video was first published, in {@link W3CDateFormat}. */
- public Options publicationDate(Date publicationDate) {
+ public Options publicationDate(OffsetDateTime publicationDate) {
this.publicationDate = publicationDate;
return this;
}
@@ -308,7 +308,7 @@ public Integer getViewCount() {
}
/** Retrieves the {@link Options#publicationDate}*/
- public Date getPublicationDate() {
+ public OffsetDateTime getPublicationDate() {
return publicationDate;
}
diff --git a/src/main/java/com/redfin/sitemapgenerator/ISitemapUrl.java b/src/main/java/com/redfin/sitemapgenerator/ISitemapUrl.java
index 27323d2..02b47d5 100644
--- a/src/main/java/com/redfin/sitemapgenerator/ISitemapUrl.java
+++ b/src/main/java/com/redfin/sitemapgenerator/ISitemapUrl.java
@@ -1,11 +1,11 @@
package com.redfin.sitemapgenerator;
import java.net.URL;
-import java.util.Date;
+import java.time.OffsetDateTime;
public interface ISitemapUrl {
- Date getLastMod();
+ OffsetDateTime getLastMod();
URL getUrl();
diff --git a/src/main/java/com/redfin/sitemapgenerator/SitemapGenerator.java b/src/main/java/com/redfin/sitemapgenerator/SitemapGenerator.java
index 6939e28..eba70d5 100644
--- a/src/main/java/com/redfin/sitemapgenerator/SitemapGenerator.java
+++ b/src/main/java/com/redfin/sitemapgenerator/SitemapGenerator.java
@@ -34,9 +34,9 @@ public SitemapGenerator(AbstractSitemapGeneratorOptions> options, ISitemapUrlR
baseDir = options.baseDir;
baseUrl = options.baseUrl;
fileNamePrefix = options.fileNamePrefix;
- W3CDateFormat dateFormat = options.dateFormat;
- if (dateFormat == null) dateFormat = new W3CDateFormat();
- this.dateFormat = dateFormat;
+ W3CDateFormat dateFormatter = options.dateFormat;
+ if (dateFormatter == null) dateFormatter = W3CDateFormat.AUTO;
+ this.dateFormat = dateFormatter;
allowEmptySitemap = options.allowEmptySitemap;
allowMultipleSitemaps = options.allowMultipleSitemaps;
maxUrls = options.maxUrls;
diff --git a/src/main/java/com/redfin/sitemapgenerator/SitemapIndexGenerator.java b/src/main/java/com/redfin/sitemapgenerator/SitemapIndexGenerator.java
index 997e9b7..0f92e5e 100644
--- a/src/main/java/com/redfin/sitemapgenerator/SitemapIndexGenerator.java
+++ b/src/main/java/com/redfin/sitemapgenerator/SitemapIndexGenerator.java
@@ -8,8 +8,10 @@
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.OffsetDateTime;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
/**
@@ -24,7 +26,7 @@ public class SitemapIndexGenerator {
private final List urls = new ArrayList<>();
private final int maxUrls;
private final W3CDateFormat dateFormat;
- private final Date defaultLastMod;
+ private final OffsetDateTime defaultLastMod;
private final boolean autoValidate;
/** Options to configure sitemap index generation */
@@ -34,7 +36,7 @@ public static class Options {
private W3CDateFormat dateFormat = null;
private boolean allowEmptyIndex = false;
private int maxUrls = SitemapConstants.MAX_SITEMAPS_PER_INDEX;
- private Date defaultLastMod = new Date();
+ private OffsetDateTime defaultLastMod = OffsetDateTime.now();
private boolean autoValidate = false;
// TODO GZIP? Is that legal for a sitemap index?
@@ -55,7 +57,7 @@ public Options(URL baseUrl, File outFile) {
public Options(String baseUrl, File outFile) throws MalformedURLException {
this(new URL(baseUrl), outFile);
}
- /** The date formatter, typically configured with a {@link W3CDateFormat.Pattern} and/or a time zone */
+ /** The date formatter, typically configured with a {@link W3CDateFormat} and/or a time zone */
public Options dateFormat(W3CDateFormat dateFormat) {
this.dateFormat = dateFormat;
return this;
@@ -89,7 +91,7 @@ Options maxUrls(int maxUrls) {
* now, but you can pass in null to omit a lastMod entirely. We don't
* recommend this; Google may not like you as much.
*/
- public Options defaultLastMod(Date defaultLastMod) {
+ public Options defaultLastMod(OffsetDateTime defaultLastMod) {
this.defaultLastMod = defaultLastMod;
return this;
}
@@ -132,9 +134,9 @@ private SitemapIndexGenerator(Options options) {
this.outFile = options.outFile;
this.allowEmptyIndex = options.allowEmptyIndex;
this.maxUrls = options.maxUrls;
- W3CDateFormat dateFormat = options.dateFormat;
- if (dateFormat == null) dateFormat = new W3CDateFormat();
- this.dateFormat = dateFormat;
+ W3CDateFormat dateFormatter = options.dateFormat;
+ if (dateFormatter == null) dateFormatter = W3CDateFormat.AUTO;
+ this.dateFormat = dateFormatter;
this.defaultLastMod = options.defaultLastMod;
this.autoValidate = options.autoValidate;
}
@@ -184,12 +186,12 @@ public SitemapIndexGenerator addUrl(URL url) {
}
/** Adds a single sitemap to the index */
- public SitemapIndexGenerator addUrl(URL url, Date lastMod) {
+ public SitemapIndexGenerator addUrl(URL url, OffsetDateTime lastMod) {
return addUrl(new SitemapIndexUrl(url, lastMod));
}
/** Adds a single sitemap to the index */
- public SitemapIndexGenerator addUrl(String url, Date lastMod) throws MalformedURLException {
+ public SitemapIndexGenerator addUrl(String url, OffsetDateTime lastMod) throws MalformedURLException {
return addUrl(new SitemapIndexUrl(url, lastMod));
}
@@ -258,7 +260,7 @@ private void writeAsString(StringBuilder sb) {
sb.append(" ");
sb.append(UrlUtils.escapeXml(url.url.toString()));
sb.append("\n");
- Date lastMod = url.lastMod;
+ OffsetDateTime lastMod = url.lastMod;
if (lastMod == null) lastMod = defaultLastMod;
diff --git a/src/main/java/com/redfin/sitemapgenerator/SitemapIndexUrl.java b/src/main/java/com/redfin/sitemapgenerator/SitemapIndexUrl.java
index d19a953..d71ff5b 100644
--- a/src/main/java/com/redfin/sitemapgenerator/SitemapIndexUrl.java
+++ b/src/main/java/com/redfin/sitemapgenerator/SitemapIndexUrl.java
@@ -2,7 +2,7 @@
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.Date;
+import java.time.OffsetDateTime;
/**
* Represents a single sitemap for inclusion in a sitemap index.
@@ -11,24 +11,24 @@
*/
public class SitemapIndexUrl {
final URL url;
- final Date lastMod;
+ final OffsetDateTime lastMod;
/** Configures the sitemap URL with a specified lastMod */
- public SitemapIndexUrl(URL url, Date lastMod) {
+ public SitemapIndexUrl(URL url, OffsetDateTime lastMod) {
this.url = url;
this.lastMod = lastMod;
}
/** Configures the sitemap URL with a specified lastMod */
- public SitemapIndexUrl(String url, Date lastMod) throws MalformedURLException {
+ public SitemapIndexUrl(String url, OffsetDateTime lastMod) throws MalformedURLException {
this(new URL(url), lastMod);
}
- /** Configures the sitemap URL with no specified lastMod; we'll use {@link SitemapIndexGenerator.Options#defaultLastMod(Date)} or leave it blank if no default is specified */
+ /** Configures the sitemap URL with no specified lastMod; we'll use {@link SitemapIndexGenerator.Options#defaultLastMod(OffsetDateTime)} or leave it blank if no default is specified */
public SitemapIndexUrl(URL url) {
this(url, null);
}
- /** Configures the sitemap URL with no specified lastMod; we'll use {@link SitemapIndexGenerator.Options#defaultLastMod(Date)} or leave it blank if no default is specified */
+ /** Configures the sitemap URL with no specified lastMod; we'll use {@link SitemapIndexGenerator.Options#defaultLastMod(OffsetDateTime)} or leave it blank if no default is specified */
public SitemapIndexUrl(String url) throws MalformedURLException {
this(new URL(url));
}
diff --git a/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java b/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java
index ce8a40c..a352178 100644
--- a/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java
+++ b/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java
@@ -1,29 +1,28 @@
/**
- *
+ *
*/
package com.redfin.sitemapgenerator;
import java.text.DateFormat;
-import java.text.FieldPosition;
import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.GregorianCalendar;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoField;
+import java.util.List;
+import java.util.Locale;
import java.util.Objects;
-import java.util.TimeZone;
-
-import static java.util.Calendar.HOUR_OF_DAY;
-import static java.util.Calendar.MILLISECOND;
-import static java.util.Calendar.MINUTE;
-import static java.util.Calendar.SECOND;
/**
* Formats and parses dates in the six defined W3C date time formats. These formats are described in
* "Date and Time Formats",
* https://www.w3.org/TR/NOTE-datetime.
- *
+ *
* The formats are:
- *
+ *
*
* - YEAR: YYYY (eg 1997)
*
- MONTH: YYYY-MM (eg 1997-07)
@@ -32,157 +31,175 @@
*
- SECOND: YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
*
- MILLISECOND: YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
*
- *
+ *
* Note that W3C timezone designators (TZD) are either the letter "Z" (for GMT) or a pattern like "+00:30" or "-08:00". This is unlike
* RFC 822 timezones generated by SimpleDateFormat, which omit the ":" like this: "+0030" or "-0800".
- *
+ *
* This class allows you to either specify which format pattern to use, or (by default) to
* automatically guess which pattern to use (AUTO mode). When parsing in AUTO mode, we'll try parsing using each pattern
* until we find one that works. When formatting in AUTO mode, we'll use this algorithm:
- *
+ *
*
- If the date has fractional milliseconds (e.g. 2009-06-06T19:49:04.45Z) we'll use the MILLISECOND pattern
*
- Otherwise, if the date has non-zero seconds (e.g. 2009-06-06T19:49:04Z) we'll use the SECOND pattern
*
- Otherwise, if the date is not at exactly midnight (e.g. 2009-06-06T19:49Z) we'll use the MINUTE pattern
*
- Otherwise, we'll use the DAY pattern. If you want to format using the MONTH or YEAR pattern, you must declare it explicitly.
*
- *
- * Finally note that, like all classes that inherit from DateFormat, this class is not thread-safe. Also note that you
- * can explicitly specify the timezone to use for formatting using the {@link #setTimeZone(TimeZone)} method.
- *
+ *
* @author Dan Fabulich
* @see Date and Time Formats
*/
-public class W3CDateFormat extends SimpleDateFormat {
- private static final long serialVersionUID = -5733368073260485802L;
-
- /** The six patterns defined by W3C, plus {@link #AUTO} configuration */
- public enum Pattern {
- /** "yyyy-MM-dd'T'HH:mm:ss.SSSZ" */
- MILLISECOND("yyyy-MM-dd'T'HH:mm:ss.SSSZ", true),
- /** "yyyy-MM-dd'T'HH:mm:ssZ" */
- SECOND("yyyy-MM-dd'T'HH:mm:ssZ", true),
- /** "yyyy-MM-dd'T'HH:mmZ" */
- MINUTE("yyyy-MM-dd'T'HH:mmZ", true),
- /** "yyyy-MM-dd" */
- DAY("yyyy-MM-dd", false),
- /** "yyyy-MM" */
- MONTH("yyyy-MM", false),
- /** "yyyy" */
- YEAR("yyyy", false),
- /** Automatically compute the right pattern to use */
- AUTO("", true);
-
- private final String pattern;
- private final boolean includeTimeZone;
-
- Pattern(String pattern, boolean includeTimeZone) {
- this.pattern = pattern;
- this.includeTimeZone = includeTimeZone;
- }
- }
-
- private final Pattern pattern;
- /** The GMT ("zulu") time zone, for your convenience */
- public static final TimeZone ZULU = TimeZone.getTimeZone("GMT");
-
- /** Build a formatter in AUTO mode */
- public W3CDateFormat() {
- this(Pattern.AUTO);
- }
-
- /** Build a formatter using the specified Pattern, or AUTO mode */
- public W3CDateFormat(Pattern pattern) {
- super(pattern.pattern);
- this.pattern = pattern;
- }
-
- /** This is what you override when you extend DateFormat; use {@link DateFormat#format(Date)} instead */
- @Override
- public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {
- boolean includeTimeZone = pattern.includeTimeZone;
- if (pattern == Pattern.AUTO) {
- includeTimeZone = autoFormat(date);
- }
- super.format(date, toAppendTo, pos);
- if (includeTimeZone) convertRfc822TimeZoneToW3c(toAppendTo);
- return toAppendTo;
- }
-
- private boolean applyPattern(Pattern pattern) {
- applyPattern(pattern.pattern);
- return pattern.includeTimeZone;
- }
-
- private boolean autoFormat(Date date) {
- if (calendar == null) calendar = new GregorianCalendar();
- calendar.setTime(date);
- boolean hasMillis = calendar.get(MILLISECOND) > 0;
- if (hasMillis) {
- return applyPattern(Pattern.MILLISECOND);
- }
- boolean hasSeconds = calendar.get(SECOND) > 0;
- if (hasSeconds) {
- return applyPattern(Pattern.SECOND);
- }
- boolean hasTime = (calendar.get(HOUR_OF_DAY) + calendar.get(MINUTE)) > 0;
- if (hasTime) {
- return applyPattern(Pattern.MINUTE);
- }
- return applyPattern(Pattern.DAY);
- }
-
- /** This is what you override when you extend DateFormat; use {@link DateFormat#parse(String)} instead */
- @Override
- public Date parse(String text, ParsePosition pos) {
- text = convertW3cTimeZoneToRfc822(text);
- if (pattern == Pattern.AUTO) {
- return autoParse(text, pos);
- }
- return super.parse(text, pos);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof W3CDateFormat)) return false;
- if (!super.equals(o)) return false;
- W3CDateFormat that = (W3CDateFormat) o;
- return pattern == that.pattern;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(super.hashCode(), pattern);
- }
-
- private Date autoParse(String text, ParsePosition pos) {
- for (Pattern pattern : Pattern.values()) {
- if (pattern == Pattern.AUTO) continue;
- applyPattern(pattern);
- Date out = super.parse(text, pos);
- if (out != null) return out;
- }
- return null; // this will force a ParseException
- }
-
- private void convertRfc822TimeZoneToW3c(StringBuffer toAppendTo) {
- int length = toAppendTo.length();
- if (ZULU.equals(calendar.getTimeZone())) {
- toAppendTo.replace(length - 5, length, "Z");
- } else {
- toAppendTo.insert(length - 2, ':');
- }
- }
-
- private String convertW3cTimeZoneToRfc822(String source) {
- int length = source.length();
- if (source.endsWith("Z")) {
- return source.substring(0, length-1) + "+0000";
- }
- if (source.charAt(length-3) == ':') {
- return source.substring(0, length-3) + source.substring(length - 2);
- }
- return source;
- }
-
+public class W3CDateFormat {
+ public static final DateTimeFormatter FORMAT_RFC_822 = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss zzz").withZone(ZoneOffset.UTC);
+
+ private static final DateTimeFormatter FORMAT_AUTO = new DateTimeFormatterBuilder()
+ .appendPattern("yyyy[-MM[-dd]]['T'HH[:mm[:ss[.SSS]]]][XXX]")
+ .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
+ .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
+ .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
+ .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
+ .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
+ .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
+ .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
+ .toFormatter(Locale.ENGLISH);
+ public static final W3CDateFormat AUTO = new W3CDateFormat(FORMAT_AUTO, true, ZoneOffset.UTC,true);
+
+ private static final DateTimeFormatter FORMAT_MILLISECONDS = new DateTimeFormatterBuilder()
+ .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS[XXX]")
+ .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
+ .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
+ .toFormatter(Locale.ENGLISH);
+ public static final W3CDateFormat MILLISECOND = new W3CDateFormat(FORMAT_MILLISECONDS, true, ZoneOffset.UTC);
+
+ private static final DateTimeFormatter FORMAT_SECONDS = new DateTimeFormatterBuilder()
+ .appendPattern("yyyy-MM-dd'T'HH:mm:ss[XXX]")
+ .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
+ .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
+ .toFormatter(Locale.ENGLISH);
+ public static final W3CDateFormat SECOND = new W3CDateFormat(FORMAT_SECONDS, true, ZoneOffset.UTC);
+
+ private static final DateTimeFormatter FORMAT_MINUTES = new DateTimeFormatterBuilder()
+ .appendPattern("yyyy-MM-dd'T'HH:mm[XXX]")
+ .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
+ .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
+ .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
+ .toFormatter(Locale.ENGLISH);
+ public static final W3CDateFormat MINUTE = new W3CDateFormat(FORMAT_MINUTES, true, ZoneOffset.UTC);
+
+ private static final DateTimeFormatter FORMAT_DAYS = new DateTimeFormatterBuilder()
+ .appendPattern("yyyy-MM-dd")
+ .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
+ .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
+ .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
+ .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
+ .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
+ .toFormatter(Locale.ENGLISH);
+ public static final W3CDateFormat DAY = new W3CDateFormat(FORMAT_DAYS, false, ZoneOffset.UTC);
+
+ private static final DateTimeFormatter FORMAT_MONTHS = new DateTimeFormatterBuilder()
+ .appendPattern("yyyy-MM")
+ .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
+ .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
+ .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
+ .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
+ .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
+ .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
+ .toFormatter(Locale.ENGLISH);
+ public static final W3CDateFormat MONTH = new W3CDateFormat(FORMAT_MONTHS, false, ZoneOffset.UTC);
+
+ private static final DateTimeFormatter FORMAT_YEAR = new DateTimeFormatterBuilder()
+ .appendPattern("yyyy")
+ .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
+ .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
+ .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
+ .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
+ .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
+ .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
+ .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
+ .toFormatter(Locale.ENGLISH);
+ public static final W3CDateFormat YEAR = new W3CDateFormat(FORMAT_YEAR, false, ZoneOffset.UTC);
+
+ private static final List ALL_FORMATS = List.of(AUTO, MILLISECOND, SECOND, MINUTE, DAY, MONTH, YEAR);
+
+
+ private final DateTimeFormatter dateTimeFormatter;
+ private final boolean includeTimeZone;
+ private final ZoneId timeZone;
+ private final boolean isAuto;
+
+
+ public W3CDateFormat() {
+ this.dateTimeFormatter = FORMAT_AUTO;
+ isAuto = true;
+ this.includeTimeZone = true;
+ this.timeZone = ZoneOffset.UTC;
+ }
+
+ public W3CDateFormat(DateTimeFormatter formatter, boolean includeTimeZone, ZoneId zoneId) {
+ this.dateTimeFormatter = formatter;
+ this.includeTimeZone = includeTimeZone;
+ this.timeZone = zoneId;
+ this.isAuto = false;
+ }
+
+ private W3CDateFormat(DateTimeFormatter formatter, boolean includeTimeZone, ZoneId zoneId,boolean isAuto){
+ this.dateTimeFormatter = formatter;
+ this.includeTimeZone = includeTimeZone;
+ this.timeZone = zoneId;
+ this.isAuto = isAuto;
+ }
+
+ public OffsetDateTime parse(final String date) {
+ return OffsetDateTime.parse(date, dateTimeFormatter);
+ }
+
+ public W3CDateFormat withZone(final ZoneId zone) {
+ return new W3CDateFormat(dateTimeFormatter, includeTimeZone, zone,isAuto);
+ }
+
+ public String format(OffsetDateTime date) {
+ if (!ZoneOffset.UTC.equals(timeZone)) {
+ date = date.atZoneSameInstant(timeZone).toOffsetDateTime();
+ }
+
+ DateTimeFormatter formatter = dateTimeFormatter;
+ if (isAuto) {
+ formatter = autoFormat(date);
+ }
+ if (includeTimeZone) {
+ return formatter.withZone(timeZone).format(date);
+ } else {
+ return formatter.format(date);
+ }
+
+ }
+
+
+ private DateTimeFormatter autoFormat(OffsetDateTime date) {
+ if (date.get(ChronoField.MILLI_OF_SECOND) > 0) {
+ return FORMAT_MILLISECONDS;
+ } else if (date.getSecond() > 0) {
+ return FORMAT_SECONDS;
+ } else if ((date.getHour() + date.getMinute()) > 0) {
+ return FORMAT_MINUTES;
+ } else {
+ return FORMAT_DAYS;
+ }
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof W3CDateFormat)) return false;
+ if (!super.equals(o)) return false;
+ W3CDateFormat that = (W3CDateFormat) o;
+ return dateTimeFormatter == that.dateTimeFormatter;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), dateTimeFormatter);
+ }
+
+
}
\ No newline at end of file
diff --git a/src/main/java/com/redfin/sitemapgenerator/WebSitemapUrl.java b/src/main/java/com/redfin/sitemapgenerator/WebSitemapUrl.java
index 0bcc504..7a099a4 100644
--- a/src/main/java/com/redfin/sitemapgenerator/WebSitemapUrl.java
+++ b/src/main/java/com/redfin/sitemapgenerator/WebSitemapUrl.java
@@ -2,7 +2,7 @@
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.Date;
+import java.time.OffsetDateTime;
/**
* Encapsulates a single URL to be inserted into a Web sitemap (as opposed to a Geo sitemap, a Mobile sitemap, a Video sitemap, etc which are Google specific).
@@ -14,7 +14,7 @@
*/
public class WebSitemapUrl implements ISitemapUrl {
private final URL url;
- private final Date lastMod;
+ private final OffsetDateTime lastMod;
private final ChangeFreq changeFreq;
private final Double priority;
@@ -43,8 +43,10 @@ public WebSitemapUrl(Options options) {
this.priority = options.priority;
}
- /** Retrieves the {@link Options#lastMod(Date)} */
- public Date getLastMod() { return lastMod; }
+ /**
+ * Retrieves the {@link Options#lastMod(OffsetDateTime)}
+ */
+ public OffsetDateTime getLastMod() { return lastMod; }
/** Retrieves the {@link Options#changeFreq(ChangeFreq)} */
public ChangeFreq getChangeFreq() { return changeFreq; }
/** Retrieves the {@link Options#priority(Double)} */
diff --git a/src/test/java/com/redfin/sitemapgenerator/GoogleImageSitemapUrlTest.java b/src/test/java/com/redfin/sitemapgenerator/GoogleImageSitemapUrlTest.java
index 55ba63c..362d624 100644
--- a/src/test/java/com/redfin/sitemapgenerator/GoogleImageSitemapUrlTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/GoogleImageSitemapUrlTest.java
@@ -10,9 +10,7 @@
import java.util.ArrayList;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.*;
class GoogleImageSitemapUrlTest {
diff --git a/src/test/java/com/redfin/sitemapgenerator/GoogleLinkSitemapUrlTest.java b/src/test/java/com/redfin/sitemapgenerator/GoogleLinkSitemapUrlTest.java
index 62d12ac..bd85d3a 100644
--- a/src/test/java/com/redfin/sitemapgenerator/GoogleLinkSitemapUrlTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/GoogleLinkSitemapUrlTest.java
@@ -1,7 +1,6 @@
package com.redfin.sitemapgenerator;
import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java b/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java
index 22faee8..56d4f2c 100644
--- a/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java
@@ -1,12 +1,13 @@
package com.redfin.sitemapgenerator;
-import com.redfin.sitemapgenerator.W3CDateFormat.Pattern;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
-import java.util.Date;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -37,11 +38,9 @@ public void tearDown() {
@Test
void testSimpleUrl() throws Exception {
- W3CDateFormat dateFormat = new W3CDateFormat(Pattern.SECOND);
- dateFormat.setTimeZone(W3CDateFormat.ZULU);
wsg = GoogleNewsSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(dateFormat).build();
- GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl("https://www.example.com/index.html", new Date(0), "Example Title", "The Example Times", "en");
+ .dateFormat(W3CDateFormat.SECOND).build();
+ GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl("https://www.example.com/index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), "Example Title", "The Example Times", "en");
wsg.addUrl(url);
String expected = "\n" +
String.format("\n",
@@ -64,11 +63,9 @@ void testSimpleUrl() throws Exception {
@Test
void testKeywords() throws Exception {
- W3CDateFormat dateFormat = new W3CDateFormat(Pattern.SECOND);
- dateFormat.setTimeZone(W3CDateFormat.ZULU);
wsg = GoogleNewsSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(dateFormat).build();
- GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", new Date(0), "Example Title", "The Example Times", "en")
+ .dateFormat(W3CDateFormat.SECOND).build();
+ GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), "Example Title", "The Example Times", "en")
.keywords("Klaatu", "Barrata", "Nicto")
.build();
wsg.addUrl(url);
@@ -94,11 +91,9 @@ void testKeywords() throws Exception {
@Test
void testGenres() throws Exception {
- W3CDateFormat dateFormat = new W3CDateFormat(Pattern.SECOND);
- dateFormat.setTimeZone(W3CDateFormat.ZULU);
wsg = GoogleNewsSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(dateFormat).build();
- GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", new Date(0), "Example Title", "The Example Times", "en")
+ .dateFormat(W3CDateFormat.SECOND).build();
+ GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), "Example Title", "The Example Times", "en")
.genres("persbericht")
.build();
wsg.addUrl(url);
diff --git a/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java b/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java
index 498e491..3c38b6d 100644
--- a/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java
@@ -8,7 +8,9 @@
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.Date;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -68,15 +70,13 @@ void testSimpleUrl() throws Exception {
@Test
void testOptions() throws Exception {
- W3CDateFormat dateFormat = new W3CDateFormat();
- dateFormat.setTimeZone(W3CDateFormat.ZULU);
wsg = GoogleVideoSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(dateFormat).build();
+ .dateFormat(W3CDateFormat.DAY).build();
GoogleVideoSitemapUrl url = new Options(LANDING_URL, CONTENT_URL)
.playerUrl(new URL("https://www.example.com/index.swf"), true)
.thumbnailUrl(new URL("https://www.example.com/thumbnail.jpg"))
.title("This is a video!").description("A great video about dinosaurs")
- .rating(5.0).viewCount(500000).publicationDate(new Date(0)).tags("dinosaurs", "example", "awesome")
+ .rating(5.0).viewCount(500000).publicationDate(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).tags("dinosaurs", "example", "awesome")
.category("example").familyFriendly(false).durationInSeconds(60*30)
.build();
wsg.addUrl(url);
diff --git a/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java b/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java
index 9106cbb..292964a 100644
--- a/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java
@@ -9,14 +9,13 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
-import java.util.Date;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
import java.util.List;
import java.util.zip.GZIPInputStream;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
class SitemapGeneratorTest {
@@ -151,11 +150,9 @@ void testTwoUrl() throws Exception {
@Test
void testAllUrlOptions() throws Exception {
- W3CDateFormat df = new W3CDateFormat();
- df.setTimeZone(W3CDateFormat.ZULU);
- wsg = WebSitemapGenerator.builder("https://www.example.com", dir).dateFormat(df).autoValidate(true).build();
+ wsg = WebSitemapGenerator.builder("https://www.example.com", dir).dateFormat(W3CDateFormat.DAY).autoValidate(true).build();
WebSitemapUrl url = new WebSitemapUrl.Options("https://www.example.com/index.html")
- .changeFreq(ChangeFreq.DAILY).lastMod(new Date(0)).priority(1.0).build();
+ .changeFreq(ChangeFreq.DAILY).lastMod(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).priority(1.0).build();
wsg.addUrl(url);
String expected = "\n" +
String.format("\n", SitemapConstants.SITEMAP_NS_URI) +
@@ -168,7 +165,7 @@ void testAllUrlOptions() throws Exception {
"";
String sitemap = writeSingleSiteMap(wsg);
assertEquals(expected, sitemap);
-
+
TestUtil.isValidSitemap(sitemap);
}
diff --git a/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java b/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java
index f819d54..5793625 100644
--- a/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java
@@ -6,7 +6,10 @@
import java.io.File;
import java.net.MalformedURLException;
-import java.util.Date;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -58,13 +61,11 @@ public class SitemapIndexGeneratorTest {
"";
private static final String EXAMPLE = "https://www.example.com/";
- private static final W3CDateFormat ZULU = new W3CDateFormat();
File outFile;
SitemapIndexGenerator sig;
@BeforeEach
public void setUp() throws Exception {
- ZULU.setTimeZone(W3CDateFormat.ZULU);
outFile = File.createTempFile(SitemapGeneratorTest.class.getSimpleName(), ".xml");
outFile.deleteOnExit();
}
@@ -106,7 +107,7 @@ void testNoUrlsEmptyIndexAllowed() throws Exception {
@Test
void testMaxUrls() throws Exception {
sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).autoValidate(true)
- .maxUrls(10).defaultLastMod(new Date(0)).dateFormat(ZULU).build();
+ .maxUrls(10).defaultLastMod(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).dateFormat(new W3CDateFormat()).build();
for (int i = 1; i <= 9; i++) {
sig.addUrl(EXAMPLE+"sitemap"+i+".xml");
}
@@ -119,8 +120,8 @@ void testMaxUrls() throws Exception {
@Test
void testOneUrl() throws Exception {
- sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).dateFormat(ZULU).autoValidate(true).build();
- SitemapIndexUrl url = new SitemapIndexUrl(EXAMPLE+"index.html", new Date(0));
+ sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).dateFormat(new W3CDateFormat()).autoValidate(true).build();
+ SitemapIndexUrl url = new SitemapIndexUrl(EXAMPLE+"index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC));
sig.addUrl(url);
sig.write();
String actual = TestUtil.slurpFileAndDelete(outFile);
@@ -138,7 +139,7 @@ void testOneUrl() throws Exception {
@Test
void testAddByPrefix() throws MalformedURLException {
sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).autoValidate(true)
- .defaultLastMod(new Date(0)).dateFormat(ZULU).build();
+ .defaultLastMod(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).dateFormat(new W3CDateFormat()).build();
sig.addUrls("sitemap", ".xml", 10);
sig.write();
String actual = TestUtil.slurpFileAndDelete(outFile);
diff --git a/src/test/java/com/redfin/sitemapgenerator/TestUtil.java b/src/test/java/com/redfin/sitemapgenerator/TestUtil.java
index 2761fca..6325fb8 100644
--- a/src/test/java/com/redfin/sitemapgenerator/TestUtil.java
+++ b/src/test/java/com/redfin/sitemapgenerator/TestUtil.java
@@ -6,11 +6,7 @@
import org.xmlunit.validation.Validator;
import javax.xml.transform.Source;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java b/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java
index a53ffa0..e03564b 100644
--- a/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java
@@ -1,13 +1,11 @@
package com.redfin.sitemapgenerator;
-import com.redfin.sitemapgenerator.W3CDateFormat.Pattern;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
-import java.util.Date;
-import java.util.TimeZone;
+import java.time.OffsetDateTime;
public class TutorialExampleTest {
@@ -52,7 +50,7 @@ void testConfiguringWsgOptions() throws Exception {
void testConfiguringUrlOptions() throws Exception {
WebSitemapGenerator wsg = new WebSitemapGenerator("https://www.example.com", myDir);
WebSitemapUrl url = new WebSitemapUrl.Options("https://www.example.com/index.html")
- .lastMod(new Date()).priority(1.0).changeFreq(ChangeFreq.HOURLY).build();
+ .lastMod(OffsetDateTime.now()).priority(1.0).changeFreq(ChangeFreq.HOURLY).build();
// this will configure the URL with lastmod=now, priority=1.0, changefreq=hourly
wsg.addUrl(url);
wsg.write();
@@ -60,10 +58,8 @@ void testConfiguringUrlOptions() throws Exception {
@Test
void testConfiguringDateFormat() throws Exception {
- W3CDateFormat dateFormat = new W3CDateFormat(Pattern.DAY); // e.g. 2008-01-29
- dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); // Use Greenwich Mean Time timezone
WebSitemapGenerator wsg = WebSitemapGenerator.builder("https://www.example.com", myDir)
- .dateFormat(dateFormat).build(); // actually use the configured dateFormat
+ .dateFormat(W3CDateFormat.DAY).build(); // actually use the configured dateFormat
wsg.addUrl("https://www.example.com/index.html");
wsg.write();
}
diff --git a/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java b/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java
index b86b9d4..89363db 100644
--- a/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java
@@ -1,25 +1,21 @@
package com.redfin.sitemapgenerator;
-import com.redfin.sitemapgenerator.W3CDateFormat.Pattern;
import org.junit.jupiter.api.Test;
import java.text.ParseException;
-import java.util.Date;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.util.TimeZone;
-import static com.redfin.sitemapgenerator.W3CDateFormat.Pattern.AUTO;
-import static com.redfin.sitemapgenerator.W3CDateFormat.Pattern.DAY;
-import static com.redfin.sitemapgenerator.W3CDateFormat.Pattern.MILLISECOND;
-import static com.redfin.sitemapgenerator.W3CDateFormat.Pattern.MINUTE;
-import static com.redfin.sitemapgenerator.W3CDateFormat.Pattern.MONTH;
-import static com.redfin.sitemapgenerator.W3CDateFormat.Pattern.SECOND;
-import static com.redfin.sitemapgenerator.W3CDateFormat.Pattern.YEAR;
+import static com.redfin.sitemapgenerator.W3CDateFormat.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class W3CDateFormatTest {
@Test
void testFormatEpoch() {
- Date epoch = new Date(0);
+ OffsetDateTime epoch = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
verifyPatternFormat(epoch, MILLISECOND, "1970-01-01T00:00:00.000Z");
verifyPatternFormat(epoch, SECOND, "1970-01-01T00:00:00Z");
verifyPatternFormat(epoch, MINUTE, "1970-01-01T00:00Z");
@@ -31,29 +27,29 @@ void testFormatEpoch() {
@Test
void testAutoFormat() {
- Date date = new Date(0);
+ OffsetDateTime date = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
verifyPatternFormat(date, AUTO, "1970-01-01");
- date = new Date(1);
+ date = OffsetDateTime.ofInstant(Instant.ofEpochMilli(1), ZoneOffset.UTC);
verifyPatternFormat(date, AUTO, "1970-01-01T00:00:00.001Z");
- date = new Date(1000);
+ date = OffsetDateTime.ofInstant(Instant.ofEpochMilli(1000), ZoneOffset.UTC);
verifyPatternFormat(date, AUTO, "1970-01-01T00:00:01Z");
- date = new Date(60000);
+ date = OffsetDateTime.ofInstant(Instant.ofEpochMilli(60000), ZoneOffset.UTC);
verifyPatternFormat(date, AUTO, "1970-01-01T00:01Z");
- date = new Date(60000 * 60 * 24);
+ date = OffsetDateTime.ofInstant(Instant.ofEpochMilli(60000 * 60 * 24), ZoneOffset.UTC);
verifyPatternFormat(date, AUTO, "1970-01-02");
}
@Test
void testFormatTimeZone() {
- Date epoch = new Date(0);
- TimeZone tz = TimeZone.getTimeZone("PST");
- verifyPatternFormat(epoch, MILLISECOND, "1969-12-31T16:00:00.000-08:00", tz);
- verifyPatternFormat(epoch, AUTO, "1969-12-31T16:00-08:00", tz);
+ OffsetDateTime epoch = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ ZoneId tz = TimeZone.getTimeZone("PST").toZoneId();
+ verifyPatternFormat(epoch, MILLISECOND.withZone(tz), "1969-12-31T16:00:00.000-08:00", tz);
+ verifyPatternFormat(epoch, AUTO.withZone(tz), "1969-12-31T16:00-08:00", tz);
}
@Test
void testParseEpoch() throws ParseException {
- Date date = new Date(0);
+ OffsetDateTime date = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
verifyPatternParse("1970-01-01T00:00:00.000Z", MILLISECOND, date);
verifyPatternParse("1970-01-01T00:00:00Z", SECOND, date);
verifyPatternParse("1970-01-01T00:00Z", MINUTE, date);
@@ -65,7 +61,7 @@ void testParseEpoch() throws ParseException {
@Test
void testAutoParse() throws ParseException {
- Date date = new Date(0);
+ OffsetDateTime date = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
verifyPatternParse("1970-01-01T00:00:00.000Z", AUTO, date);
verifyPatternParse("1970-01-01T00:00:00Z", AUTO, date);
verifyPatternParse("1970-01-01T00:00Z", AUTO, date);
@@ -76,29 +72,26 @@ void testAutoParse() throws ParseException {
@Test
void testParseTimeZone() throws ParseException {
- Date epoch = new Date(0);
+ OffsetDateTime epoch = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
verifyPatternParse("1969-12-31T16:00:00.000-08:00", MILLISECOND, epoch);
verifyPatternParse("1969-12-31T16:00:00.000-08:00", AUTO, epoch);
}
- private void verifyPatternFormat(Date date, Pattern pattern, String expected) {
- verifyPatternFormat(date, pattern, expected, W3CDateFormat.ZULU);
+ private void verifyPatternFormat(OffsetDateTime date, W3CDateFormat pattern, String expected) {
+ verifyPatternFormat(date, pattern, expected, ZoneOffset.UTC);
}
- private void verifyPatternFormat(Date date, Pattern pattern, String expected, TimeZone tz) {
- W3CDateFormat format = new W3CDateFormat(pattern);
- format.setTimeZone(tz);
- assertEquals(expected, format.format(date), date.toString() + " " + pattern);
+ private void verifyPatternFormat(OffsetDateTime date, W3CDateFormat pattern, String expected, ZoneId tz) {
+
+ assertEquals(expected, pattern.format(date), date.toString() + " " + pattern);
}
- private void verifyPatternParse(String source, Pattern pattern, Date expected) throws ParseException {
- verifyPatternParse(source, pattern, expected, W3CDateFormat.ZULU);
+ private void verifyPatternParse(String source, W3CDateFormat pattern, OffsetDateTime expected) throws ParseException {
+ verifyPatternParse(source, pattern, expected, ZoneOffset.UTC);
}
- private void verifyPatternParse(String source, Pattern pattern, Date expected, TimeZone tz) throws ParseException {
- W3CDateFormat format = new W3CDateFormat(pattern);
- format.setTimeZone(tz);
- Date actual = format.parse(source);
+ private void verifyPatternParse(String source, W3CDateFormat pattern, OffsetDateTime expected, ZoneId tz) throws ParseException {
+ OffsetDateTime actual = pattern.parse(source).atZoneSameInstant(tz).toOffsetDateTime();
assertEquals(expected, actual, source + " " + pattern);
}
From 5b54fba7aaa7867de8f509c328e02def30832aae Mon Sep 17 00:00:00 2001
From: Brad Hall
Date: Thu, 11 Apr 2024 13:26:20 -0400
Subject: [PATCH 2/3] Updated versions and readme code
---
README.md | 14 ++++++---
pom.xml | 2 +-
.../sitemapgenerator/W3CDateFormat.java | 31 +++++++++++++------
3 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index f5321ca..bcdb041 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ First, add this as a dependency to your POM:
io.gdcc
sitemapgen4j
- 2.1.0
+ 2.2.0
```
@@ -59,12 +59,18 @@ wsg.write();
To configure the URLs, construct a WebSitemapUrl with WebSitemapUrl.Options.
```java
+import java.time.OffsetDateTime;
+
WebSitemapGenerator wsg = new WebSitemapGenerator("https://www.example.com", myDir);
WebSitemapUrl url = new WebSitemapUrl.Options("https://www.example.com/index.html")
- .lastMod(new Date()).priority(1.0).changeFreq(ChangeFreq.HOURLY).build();
+ .lastMod(OffsetDateTime.now()).priority(1.0).changeFreq(ChangeFreq.HOURLY).build();
// this will configure the URL with lastmod=now, priority=1.0, changefreq=hourly
-wsg.addUrl(url);
-wsg.write();
+wsg.
+
+addUrl(url);
+wsg.
+
+write();
```
## Configuring the date format
diff --git a/pom.xml b/pom.xml
index 9844291..1f013e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
scm:git:git://github.com:gdcc/sitemapgen4j.git
scm:git:git@github.com:gdcc/sitemapgen4j.git
https://github.com/gdcc/sitemapgen4j/
- sitemapgen4j-2.1.2
+ sitemapgen4j-2.2.0
https://github.com/gdcc/sitemapgen4j/issues
diff --git a/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java b/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java
index a352178..a7ff277 100644
--- a/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java
+++ b/src/main/java/com/redfin/sitemapgenerator/W3CDateFormat.java
@@ -3,16 +3,12 @@
*/
package com.redfin.sitemapgenerator;
-import java.text.DateFormat;
-import java.text.ParsePosition;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
-import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
-import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -21,7 +17,7 @@
* "Date and Time Formats",
* https://www.w3.org/TR/NOTE-datetime.
*
- * The formats are:
+ *
The formats are:
*
*
* - YEAR: YYYY (eg 1997)
@@ -32,7 +28,7 @@
*
- MILLISECOND: YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
*
*
- * Note that W3C timezone designators (TZD) are either the letter "Z" (for GMT) or a pattern like "+00:30" or "-08:00". This is unlike
+ * Note that W3C timezone designators (TZD) are either the letter "Z" (for GMT) or a pattern like "+00:30" or "-08:00". This is unlike
* RFC 822 timezones generated by SimpleDateFormat, which omit the ":" like this: "+0030" or "-0800".
*
* This class allows you to either specify which format pattern to use, or (by default) to
@@ -118,9 +114,6 @@ public class W3CDateFormat {
.toFormatter(Locale.ENGLISH);
public static final W3CDateFormat YEAR = new W3CDateFormat(FORMAT_YEAR, false, ZoneOffset.UTC);
- private static final List ALL_FORMATS = List.of(AUTO, MILLISECOND, SECOND, MINUTE, DAY, MONTH, YEAR);
-
-
private final DateTimeFormatter dateTimeFormatter;
private final boolean includeTimeZone;
private final ZoneId timeZone;
@@ -129,7 +122,7 @@ public class W3CDateFormat {
public W3CDateFormat() {
this.dateTimeFormatter = FORMAT_AUTO;
- isAuto = true;
+ this.isAuto = true;
this.includeTimeZone = true;
this.timeZone = ZoneOffset.UTC;
}
@@ -148,14 +141,32 @@ private W3CDateFormat(DateTimeFormatter formatter, boolean includeTimeZone, Zone
this.isAuto = isAuto;
}
+ /**
+ * Parses a string representation of a date into an OffsetDateTime object using the configured DateTimeFormatter.
+ *
+ * @param date The date string to parse.
+ * @return The parsed OffsetDateTime object.
+ */
public OffsetDateTime parse(final String date) {
return OffsetDateTime.parse(date, dateTimeFormatter);
}
+ /**
+ * Creates a new W3CDateFormat with the specified ZoneId.
+ *
+ * @param zone the desired ZoneId
+ * @return a new instance of W3CDateFormat with the specified ZoneId
+ */
public W3CDateFormat withZone(final ZoneId zone) {
return new W3CDateFormat(dateTimeFormatter, includeTimeZone, zone,isAuto);
}
+ /**
+ * Formats the given OffsetDateTime object according to the configured settings.
+ *
+ * @param date The OffsetDateTime object to be formatted.
+ * @return The formatted date as a String.
+ */
public String format(OffsetDateTime date) {
if (!ZoneOffset.UTC.equals(timeZone)) {
date = date.atZoneSameInstant(timeZone).toOffsetDateTime();
From 915b17d76045d352ca0c3c831749d891b8ce8931 Mon Sep 17 00:00:00 2001
From: Brad Hall
Date: Thu, 11 Apr 2024 14:07:13 -0400
Subject: [PATCH 3/3] Fixed accidental changes to unit tests
---
TODO.txt | 1 -
.../AbstractSitemapGeneratorOptions.java | 2 +-
.../sitemapgenerator/AbstractSitemapUrlOptions.java | 2 +-
.../sitemapgenerator/GoogleNewsSitemapUrlTest.java | 13 +++++++------
.../sitemapgenerator/GoogleVideoSitemapUrlTest.java | 4 ++--
.../sitemapgenerator/SitemapGeneratorTest.java | 4 ++--
.../sitemapgenerator/SitemapIndexGeneratorTest.java | 13 ++++++-------
.../java/com/redfin/sitemapgenerator/TestUtil.java | 13 ++++++++++++-
.../sitemapgenerator/TutorialExampleTest.java | 3 ++-
.../redfin/sitemapgenerator/W3CDateFormatTest.java | 12 ++++++------
10 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/TODO.txt b/TODO.txt
index a97fab7..71111a2 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -1,4 +1,3 @@
-Migrate to java.time
Migrate to java.nio
Ping search engines
diff --git a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java
index 8479ac3..bac710c 100644
--- a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java
+++ b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapGeneratorOptions.java
@@ -56,7 +56,7 @@ public T allowMultipleSitemaps(boolean allowMultipleSitemaps) {
this.allowMultipleSitemaps = allowMultipleSitemaps;
return getThis();
}
- /** The date formatter, typically configured with a {@link DateTimeFormatter} and/or a time zone */
+ /** The date formatter, typically configured with a {@link W3CDateFormat} and/or a time zone */
public T dateFormat(W3CDateFormat dateFormat) {
this.dateFormat = dateFormat;
return getThis();
diff --git a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java
index 56eaf01..284b2de 100644
--- a/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java
+++ b/src/main/java/com/redfin/sitemapgenerator/AbstractSitemapUrlOptions.java
@@ -45,7 +45,7 @@ public T lastMod(OffsetDateTime lastMod) {
* @see W3CDateFormat
*/
public T lastMod(String lastMod) throws ParseException {
- this.lastMod = W3CDateFormat.DAY.parse(lastMod);
+ this.lastMod = W3CDateFormat.AUTO.parse(lastMod);
return getThis();
}
diff --git a/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java b/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java
index 56d4f2c..50c30a3 100644
--- a/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/GoogleNewsSitemapUrlTest.java
@@ -7,6 +7,7 @@
import java.io.File;
import java.time.Instant;
import java.time.OffsetDateTime;
+import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.List;
@@ -39,8 +40,8 @@ public void tearDown() {
@Test
void testSimpleUrl() throws Exception {
wsg = GoogleNewsSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(W3CDateFormat.SECOND).build();
- GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl("https://www.example.com/index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), "Example Title", "The Example Times", "en");
+ .dateFormat(W3CDateFormat.SECOND.withZone(ZoneOffset.UTC)).build();
+ GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl("https://www.example.com/index.html", TestUtil.getEpochOffsetDateTime(), "Example Title", "The Example Times", "en");
wsg.addUrl(url);
String expected = "\n" +
String.format("\n",
@@ -64,8 +65,8 @@ void testSimpleUrl() throws Exception {
@Test
void testKeywords() throws Exception {
wsg = GoogleNewsSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(W3CDateFormat.SECOND).build();
- GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), "Example Title", "The Example Times", "en")
+ .dateFormat(W3CDateFormat.SECOND.withZone(ZoneOffset.UTC)).build();
+ GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", TestUtil.getEpochOffsetDateTime(), "Example Title", "The Example Times", "en")
.keywords("Klaatu", "Barrata", "Nicto")
.build();
wsg.addUrl(url);
@@ -92,8 +93,8 @@ void testKeywords() throws Exception {
@Test
void testGenres() throws Exception {
wsg = GoogleNewsSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(W3CDateFormat.SECOND).build();
- GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), "Example Title", "The Example Times", "en")
+ .dateFormat(W3CDateFormat.SECOND.withZone(ZoneOffset.UTC)).build();
+ GoogleNewsSitemapUrl url = new GoogleNewsSitemapUrl.Options("https://www.example.com/index.html", TestUtil.getEpochOffsetDateTime(), "Example Title", "The Example Times", "en")
.genres("persbericht")
.build();
wsg.addUrl(url);
diff --git a/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java b/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java
index 3c38b6d..e9a6b69 100644
--- a/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/GoogleVideoSitemapUrlTest.java
@@ -71,12 +71,12 @@ void testSimpleUrl() throws Exception {
@Test
void testOptions() throws Exception {
wsg = GoogleVideoSitemapGenerator.builder("https://www.example.com", dir)
- .dateFormat(W3CDateFormat.DAY).build();
+ .dateFormat(W3CDateFormat.AUTO.withZone(ZoneOffset.UTC)).build();
GoogleVideoSitemapUrl url = new Options(LANDING_URL, CONTENT_URL)
.playerUrl(new URL("https://www.example.com/index.swf"), true)
.thumbnailUrl(new URL("https://www.example.com/thumbnail.jpg"))
.title("This is a video!").description("A great video about dinosaurs")
- .rating(5.0).viewCount(500000).publicationDate(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).tags("dinosaurs", "example", "awesome")
+ .rating(5.0).viewCount(500000).publicationDate(TestUtil.getEpochOffsetDateTime()).tags("dinosaurs", "example", "awesome")
.category("example").familyFriendly(false).durationInSeconds(60*30)
.build();
wsg.addUrl(url);
diff --git a/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java b/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java
index 292964a..3142fb7 100644
--- a/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/SitemapGeneratorTest.java
@@ -150,9 +150,9 @@ void testTwoUrl() throws Exception {
@Test
void testAllUrlOptions() throws Exception {
- wsg = WebSitemapGenerator.builder("https://www.example.com", dir).dateFormat(W3CDateFormat.DAY).autoValidate(true).build();
+ wsg = WebSitemapGenerator.builder("https://www.example.com", dir).dateFormat(W3CDateFormat.AUTO.withZone(ZoneOffset.UTC)).autoValidate(true).build();
WebSitemapUrl url = new WebSitemapUrl.Options("https://www.example.com/index.html")
- .changeFreq(ChangeFreq.DAILY).lastMod(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).priority(1.0).build();
+ .changeFreq(ChangeFreq.DAILY).lastMod(TestUtil.getEpochOffsetDateTime()).priority(1.0).build();
wsg.addUrl(url);
String expected = "\n" +
String.format("\n", SitemapConstants.SITEMAP_NS_URI) +
diff --git a/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java b/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java
index 5793625..78749dd 100644
--- a/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/SitemapIndexGeneratorTest.java
@@ -6,16 +6,15 @@
import java.io.File;
import java.net.MalformedURLException;
-import java.time.Instant;
-import java.time.OffsetDateTime;
import java.time.ZoneOffset;
-import java.time.format.DateTimeFormatter;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class SitemapIndexGeneratorTest {
+ private static final W3CDateFormat ZULU = new W3CDateFormat().withZone(ZoneOffset.UTC);
+
private static final String INDEX = "\n" +
String.format("\n", SitemapConstants.SITEMAP_NS_URI) +
" \n" +
@@ -107,7 +106,7 @@ void testNoUrlsEmptyIndexAllowed() throws Exception {
@Test
void testMaxUrls() throws Exception {
sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).autoValidate(true)
- .maxUrls(10).defaultLastMod(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).dateFormat(new W3CDateFormat()).build();
+ .maxUrls(10).defaultLastMod(TestUtil.getEpochOffsetDateTime()).dateFormat(ZULU).build();
for (int i = 1; i <= 9; i++) {
sig.addUrl(EXAMPLE+"sitemap"+i+".xml");
}
@@ -120,8 +119,8 @@ void testMaxUrls() throws Exception {
@Test
void testOneUrl() throws Exception {
- sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).dateFormat(new W3CDateFormat()).autoValidate(true).build();
- SitemapIndexUrl url = new SitemapIndexUrl(EXAMPLE+"index.html", OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC));
+ sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).dateFormat(ZULU).autoValidate(true).build();
+ SitemapIndexUrl url = new SitemapIndexUrl(EXAMPLE+"index.html", TestUtil.getEpochOffsetDateTime());
sig.addUrl(url);
sig.write();
String actual = TestUtil.slurpFileAndDelete(outFile);
@@ -139,7 +138,7 @@ void testOneUrl() throws Exception {
@Test
void testAddByPrefix() throws MalformedURLException {
sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).autoValidate(true)
- .defaultLastMod(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)).dateFormat(new W3CDateFormat()).build();
+ .defaultLastMod(TestUtil.getEpochOffsetDateTime()).dateFormat(ZULU).build();
sig.addUrls("sitemap", ".xml", 10);
sig.write();
String actual = TestUtil.slurpFileAndDelete(outFile);
diff --git a/src/test/java/com/redfin/sitemapgenerator/TestUtil.java b/src/test/java/com/redfin/sitemapgenerator/TestUtil.java
index 6325fb8..6239b48 100644
--- a/src/test/java/com/redfin/sitemapgenerator/TestUtil.java
+++ b/src/test/java/com/redfin/sitemapgenerator/TestUtil.java
@@ -6,7 +6,14 @@
import org.xmlunit.validation.Validator;
import javax.xml.transform.Source;
-import java.io.*;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -55,4 +62,8 @@ public static void isValidSitemap(String xml) {
ValidationResult vr = validator.validateInstance(Input.fromString(xml).build());
assertTrue(vr.isValid(), vr.getProblems().toString());
}
+
+ public static OffsetDateTime getEpochOffsetDateTime(){
+ return OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ }
}
diff --git a/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java b/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java
index e03564b..4287d12 100644
--- a/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/TutorialExampleTest.java
@@ -6,6 +6,7 @@
import java.io.File;
import java.time.OffsetDateTime;
+import java.util.TimeZone;
public class TutorialExampleTest {
@@ -59,7 +60,7 @@ void testConfiguringUrlOptions() throws Exception {
@Test
void testConfiguringDateFormat() throws Exception {
WebSitemapGenerator wsg = WebSitemapGenerator.builder("https://www.example.com", myDir)
- .dateFormat(W3CDateFormat.DAY).build(); // actually use the configured dateFormat
+ .dateFormat(W3CDateFormat.DAY.withZone(TimeZone.getTimeZone("GMT").toZoneId())).build(); // actually use the configured dateFormat
wsg.addUrl("https://www.example.com/index.html");
wsg.write();
}
diff --git a/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java b/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java
index 89363db..dfc3121 100644
--- a/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java
+++ b/src/test/java/com/redfin/sitemapgenerator/W3CDateFormatTest.java
@@ -15,7 +15,7 @@
public class W3CDateFormatTest {
@Test
void testFormatEpoch() {
- OffsetDateTime epoch = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ OffsetDateTime epoch = TestUtil.getEpochOffsetDateTime();
verifyPatternFormat(epoch, MILLISECOND, "1970-01-01T00:00:00.000Z");
verifyPatternFormat(epoch, SECOND, "1970-01-01T00:00:00Z");
verifyPatternFormat(epoch, MINUTE, "1970-01-01T00:00Z");
@@ -27,7 +27,7 @@ void testFormatEpoch() {
@Test
void testAutoFormat() {
- OffsetDateTime date = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ OffsetDateTime date = TestUtil.getEpochOffsetDateTime();
verifyPatternFormat(date, AUTO, "1970-01-01");
date = OffsetDateTime.ofInstant(Instant.ofEpochMilli(1), ZoneOffset.UTC);
verifyPatternFormat(date, AUTO, "1970-01-01T00:00:00.001Z");
@@ -41,7 +41,7 @@ void testAutoFormat() {
@Test
void testFormatTimeZone() {
- OffsetDateTime epoch = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ OffsetDateTime epoch = TestUtil.getEpochOffsetDateTime();
ZoneId tz = TimeZone.getTimeZone("PST").toZoneId();
verifyPatternFormat(epoch, MILLISECOND.withZone(tz), "1969-12-31T16:00:00.000-08:00", tz);
verifyPatternFormat(epoch, AUTO.withZone(tz), "1969-12-31T16:00-08:00", tz);
@@ -49,7 +49,7 @@ void testFormatTimeZone() {
@Test
void testParseEpoch() throws ParseException {
- OffsetDateTime date = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ OffsetDateTime date = TestUtil.getEpochOffsetDateTime();
verifyPatternParse("1970-01-01T00:00:00.000Z", MILLISECOND, date);
verifyPatternParse("1970-01-01T00:00:00Z", SECOND, date);
verifyPatternParse("1970-01-01T00:00Z", MINUTE, date);
@@ -61,7 +61,7 @@ void testParseEpoch() throws ParseException {
@Test
void testAutoParse() throws ParseException {
- OffsetDateTime date = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ OffsetDateTime date = TestUtil.getEpochOffsetDateTime();
verifyPatternParse("1970-01-01T00:00:00.000Z", AUTO, date);
verifyPatternParse("1970-01-01T00:00:00Z", AUTO, date);
verifyPatternParse("1970-01-01T00:00Z", AUTO, date);
@@ -72,7 +72,7 @@ void testAutoParse() throws ParseException {
@Test
void testParseTimeZone() throws ParseException {
- OffsetDateTime epoch = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
+ OffsetDateTime epoch = TestUtil.getEpochOffsetDateTime();
verifyPatternParse("1969-12-31T16:00:00.000-08:00", MILLISECOND, epoch);
verifyPatternParse("1969-12-31T16:00:00.000-08:00", AUTO, epoch);
}