commit 14a6e590853aaf8e151125bf8ae60ed82b654cf3 Author: Karsten Loesing karsten.loesing@gmx.net Date: Tue Apr 8 23:17:32 2014 +0200
Move date parsing and formatting to util class.
Suggested by SonarQube to avoid code repetition. --- .../onionoo/BandwidthDocumentWriter.java | 11 +-- src/org/torproject/onionoo/BandwidthStatus.java | 85 ++++++++---------- .../torproject/onionoo/BandwidthStatusUpdater.java | 42 ++++----- .../torproject/onionoo/ClientsDocumentWriter.java | 9 +- src/org/torproject/onionoo/ClientsStatus.java | 25 ++---- .../torproject/onionoo/ClientsStatusUpdater.java | 7 +- src/org/torproject/onionoo/DateTimeHelper.java | 57 +++++++++++++ .../torproject/onionoo/DetailsDocumentWriter.java | 18 ++-- .../onionoo/NodeDetailsStatusUpdater.java | 18 +--- src/org/torproject/onionoo/NodeStatus.java | 55 ++++++------ src/org/torproject/onionoo/ResponseBuilder.java | 9 +- .../torproject/onionoo/UptimeDocumentWriter.java | 9 +- src/org/torproject/onionoo/UptimeStatus.java | 21 ++--- .../torproject/onionoo/WeightsDocumentWriter.java | 9 +- src/org/torproject/onionoo/WeightsStatus.java | 90 +++++++++----------- .../torproject/onionoo/WeightsStatusUpdater.java | 7 +- 16 files changed, 209 insertions(+), 263 deletions(-)
diff --git a/src/org/torproject/onionoo/BandwidthDocumentWriter.java b/src/org/torproject/onionoo/BandwidthDocumentWriter.java index 754c8f3..68912c7 100644 --- a/src/org/torproject/onionoo/BandwidthDocumentWriter.java +++ b/src/org/torproject/onionoo/BandwidthDocumentWriter.java @@ -2,7 +2,6 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -10,7 +9,6 @@ import java.util.Locale; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone;
public class BandwidthDocumentWriter implements FingerprintListener, DocumentWriter{ @@ -21,16 +19,11 @@ public class BandwidthDocumentWriter implements FingerprintListener,
private long now;
- private SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - public BandwidthDocumentWriter(DescriptorSource descriptorSource, DocumentStore documentStore, Time time) { this.descriptorSource = descriptorSource; this.documentStore = documentStore; this.now = time.currentTimeMillis(); - this.dateTimeFormat.setLenient(false); - this.dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); this.registerFingerprintListeners(); }
@@ -161,9 +154,9 @@ public class BandwidthDocumentWriter implements FingerprintListener, StringBuilder sb2 = new StringBuilder(); sb2.append(""" + graphName + "":{" + ""first":"" - + this.dateTimeFormat.format(firstDataPointMillis) + ""," + + DateTimeHelper.format(firstDataPointMillis) + ""," + ""last":"" - + this.dateTimeFormat.format(lastDataPointMillis) + ""," + + DateTimeHelper.format(lastDataPointMillis) + ""," +""interval":" + String.valueOf(dataPointInterval / 1000L) + ","factor":" + String.format(Locale.US, "%.3f", factor) + ","count":" + String.valueOf(count) + ","values":["); diff --git a/src/org/torproject/onionoo/BandwidthStatus.java b/src/org/torproject/onionoo/BandwidthStatus.java index fd3c36e..00e8ca8 100644 --- a/src/org/torproject/onionoo/BandwidthStatus.java +++ b/src/org/torproject/onionoo/BandwidthStatus.java @@ -2,11 +2,8 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Scanner; import java.util.SortedMap; -import java.util.TimeZone; import java.util.TreeMap;
class BandwidthStatus extends Document { @@ -16,62 +13,50 @@ class BandwidthStatus extends Document { SortedMap<Long, long[]> readHistory = new TreeMap<Long, long[]>();
public void fromDocumentString(String documentString) { - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setLenient(false); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - try { - Scanner s = new Scanner(documentString); - while (s.hasNextLine()) { - String line = s.nextLine(); - String[] parts = line.split(" "); - if (parts.length != 6) { - System.err.println("Illegal line '" + line + "' in bandwidth " - + "history. Skipping this line."); - continue; - } - SortedMap<Long, long[]> history = parts[0].equals("r") - ? readHistory : writeHistory; - long startMillis = dateTimeFormat.parse(parts[1] + " " - + parts[2]).getTime(); - long endMillis = dateTimeFormat.parse(parts[3] + " " - + parts[4]).getTime(); - long bandwidth = Long.parseLong(parts[5]); - long previousEndMillis = history.headMap(startMillis).isEmpty() - ? startMillis - : history.get(history.headMap(startMillis).lastKey())[1]; - long nextStartMillis = history.tailMap(startMillis).isEmpty() - ? endMillis : history.tailMap(startMillis).firstKey(); - if (previousEndMillis <= startMillis && - nextStartMillis >= endMillis) { - history.put(startMillis, new long[] { startMillis, endMillis, - bandwidth }); - } + Scanner s = new Scanner(documentString); + while (s.hasNextLine()) { + String line = s.nextLine(); + String[] parts = line.split(" "); + if (parts.length != 6) { + System.err.println("Illegal line '" + line + "' in bandwidth " + + "history. Skipping this line."); + continue; + } + SortedMap<Long, long[]> history = parts[0].equals("r") + ? readHistory : writeHistory; + long startMillis = DateTimeHelper.parse(parts[1] + " " + parts[2]); + long endMillis = DateTimeHelper.parse(parts[3] + " " + parts[4]); + if (startMillis < 0L || endMillis < 0L) { + System.err.println("Could not parse timestamp while reading " + + "bandwidth history. Skipping."); + break; + } + long bandwidth = Long.parseLong(parts[5]); + long previousEndMillis = history.headMap(startMillis).isEmpty() + ? startMillis + : history.get(history.headMap(startMillis).lastKey())[1]; + long nextStartMillis = history.tailMap(startMillis).isEmpty() + ? endMillis : history.tailMap(startMillis).firstKey(); + if (previousEndMillis <= startMillis && + nextStartMillis >= endMillis) { + history.put(startMillis, new long[] { startMillis, endMillis, + bandwidth }); } - s.close(); - } catch (ParseException e) { - System.err.println("Could not parse timestamp while reading " - + "bandwidth history. Skipping."); - e.printStackTrace(); } - + s.close(); }
public String toDocumentString() { - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setLenient(false); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); StringBuilder sb = new StringBuilder(); for (long[] v : writeHistory.values()) { - sb.append("w " + dateTimeFormat.format(v[0]) + " " - + dateTimeFormat.format(v[1]) + " " - + String.valueOf(v[2]) + "\n"); + sb.append("w " + DateTimeHelper.format(v[0]) + " " + + DateTimeHelper.format(v[1]) + " " + String.valueOf(v[2]) + + "\n"); } for (long[] v : readHistory.values()) { - sb.append("r " + dateTimeFormat.format(v[0]) + " " - + dateTimeFormat.format(v[1]) + " " - + String.valueOf(v[2]) + "\n"); + sb.append("r " + DateTimeHelper.format(v[0]) + " " + + DateTimeHelper.format(v[1]) + " " + String.valueOf(v[2]) + + "\n"); } return sb.toString(); } diff --git a/src/org/torproject/onionoo/BandwidthStatusUpdater.java b/src/org/torproject/onionoo/BandwidthStatusUpdater.java index 6254260..cce56bc 100644 --- a/src/org/torproject/onionoo/BandwidthStatusUpdater.java +++ b/src/org/torproject/onionoo/BandwidthStatusUpdater.java @@ -2,10 +2,7 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.SortedMap; -import java.util.TimeZone; import java.util.TreeMap;
import org.torproject.descriptor.Descriptor; @@ -20,16 +17,11 @@ public class BandwidthStatusUpdater implements DescriptorListener,
private long now;
- private SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - public BandwidthStatusUpdater(DescriptorSource descriptorSource, DocumentStore documentStore, Time time) { this.descriptorSource = descriptorSource; this.documentStore = documentStore; this.now = time.currentTimeMillis(); - this.dateTimeFormat.setLenient(false); - this.dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); this.registerDescriptorListeners(); }
@@ -76,23 +68,22 @@ public class BandwidthStatusUpdater implements DescriptorListener, if (parts.length < 6) { return; } - try { - long endMillis = this.dateTimeFormat.parse(parts[1] + " " - + parts[2]).getTime(); - long intervalMillis = Long.parseLong(parts[3].substring(1)) * 1000L; - String[] values = parts[5].split(","); - for (int i = values.length - 1; i >= 0; i--) { - long bandwidthValue = Long.parseLong(values[i]); - long startMillis = endMillis - intervalMillis; - /* TODO Should we first check whether an interval is already - * contained in history? */ - history.put(startMillis, new long[] { startMillis, endMillis, - bandwidthValue }); - endMillis -= intervalMillis; - } - } catch (ParseException e) { + long endMillis = DateTimeHelper.parse(parts[1] + " " + parts[2]); + if (endMillis < 0L) { System.err.println("Could not parse timestamp in line '" + line + "'. Skipping."); + return; + } + long intervalMillis = Long.parseLong(parts[3].substring(1)) * 1000L; + String[] values = parts[5].split(","); + for (int i = values.length - 1; i >= 0; i--) { + long bandwidthValue = Long.parseLong(values[i]); + long startMillis = endMillis - intervalMillis; + /* TODO Should we first check whether an interval is already + * contained in history? */ + history.put(startMillis, new long[] { startMillis, endMillis, + bandwidthValue }); + endMillis -= intervalMillis; } }
@@ -101,8 +92,6 @@ public class BandwidthStatusUpdater implements DescriptorListener, new TreeMap<Long, long[]>(history); history.clear(); long lastStartMillis = 0L, lastEndMillis = 0L, lastBandwidth = 0L; - SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String lastMonthString = "1970-01"; for (long[] v : uncompressedHistory.values()) { long startMillis = v[0], endMillis = v[1], bandwidth = v[2]; @@ -120,7 +109,8 @@ public class BandwidthStatusUpdater implements DescriptorListener, } else { intervalLengthMillis = 10L * 24L * 60L * 60L * 1000L; } - String monthString = dateTimeFormat.format(startMillis); + String monthString = DateTimeHelper.format(startMillis, + DateTimeHelper.ISO_YEARMONTH_FORMAT); if (lastEndMillis == startMillis && ((lastEndMillis - 1L) / intervalLengthMillis) == ((endMillis - 1L) / intervalLengthMillis) && diff --git a/src/org/torproject/onionoo/ClientsDocumentWriter.java b/src/org/torproject/onionoo/ClientsDocumentWriter.java index 9d3b8dc..fe400d2 100644 --- a/src/org/torproject/onionoo/ClientsDocumentWriter.java +++ b/src/org/torproject/onionoo/ClientsDocumentWriter.java @@ -2,14 +2,12 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet;
@@ -221,12 +219,9 @@ public class ClientsDocumentWriter implements FingerprintListener, double factor = ((double) maxValue) / 999.0; int count = lastNonNullIndex - firstNonNullIndex + 1; StringBuilder sb = new StringBuilder(); - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); sb.append(""" + graphName + "":{" - + ""first":"" + dateTimeFormat.format(firstDataPointMillis) - + "","last":"" + dateTimeFormat.format(lastDataPointMillis) + + ""first":"" + DateTimeHelper.format(firstDataPointMillis) + + "","last":"" + DateTimeHelper.format(lastDataPointMillis) + "","interval":" + String.valueOf(dataPointInterval / 1000L) + ","factor":" + String.format(Locale.US, "%.9f", factor) + ","count":" + String.valueOf(count) + ","values":["); diff --git a/src/org/torproject/onionoo/ClientsStatus.java b/src/org/torproject/onionoo/ClientsStatus.java index c1ce80e..26f9eab 100644 --- a/src/org/torproject/onionoo/ClientsStatus.java +++ b/src/org/torproject/onionoo/ClientsStatus.java @@ -2,13 +2,10 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Map; import java.util.Scanner; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet;
@@ -45,17 +42,9 @@ class ClientsHistory implements Comparable<ClientsHistory> { if (parts.length != 8) { return null; } - long startMillis = -1L, endMillis = -1L; - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setLenient(false); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - try { - startMillis = dateTimeFormat.parse(parts[0] + " " + parts[1]). - getTime(); - endMillis = dateTimeFormat.parse(parts[2] + " " + parts[3]). - getTime(); - } catch (ParseException e) { + long startMillis = DateTimeHelper.parse(parts[0] + " " + parts[1]); + long endMillis = DateTimeHelper.parse(parts[2] + " " + parts[3]); + if (startMillis < 0L || endMillis < 0L) { return null; } if (startMillis >= endMillis) { @@ -104,12 +93,8 @@ class ClientsHistory implements Comparable<ClientsHistory> {
public String toString() { StringBuilder sb = new StringBuilder(); - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setLenient(false); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - sb.append(dateTimeFormat.format(startMillis)); - sb.append(" " + dateTimeFormat.format(endMillis)); + sb.append(DateTimeHelper.format(startMillis)); + sb.append(" " + DateTimeHelper.format(endMillis)); sb.append(" " + String.format("%.3f", this.totalResponses)); this.appendResponses(sb, this.responsesByCountry); this.appendResponses(sb, this.responsesByTransport); diff --git a/src/org/torproject/onionoo/ClientsStatusUpdater.java b/src/org/torproject/onionoo/ClientsStatusUpdater.java index e15c11a..0ce550f 100644 --- a/src/org/torproject/onionoo/ClientsStatusUpdater.java +++ b/src/org/torproject/onionoo/ClientsStatusUpdater.java @@ -2,11 +2,9 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet;
@@ -177,8 +175,6 @@ public class ClientsStatusUpdater implements DescriptorListener, SortedSet<ClientsHistory> compressedHistory = new TreeSet<ClientsHistory>(); ClientsHistory lastResponses = null; - SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String lastMonthString = "1970-01"; for (ClientsHistory responses : history) { long intervalLengthMillis; @@ -191,7 +187,8 @@ public class ClientsStatusUpdater implements DescriptorListener, } else { intervalLengthMillis = 10L * 24L * 60L * 60L * 1000L; } - String monthString = dateTimeFormat.format(responses.startMillis); + String monthString = DateTimeHelper.format(responses.startMillis, + DateTimeHelper.ISO_YEARMONTH_FORMAT); if (lastResponses != null && lastResponses.endMillis == responses.startMillis && ((lastResponses.endMillis - 1L) / intervalLengthMillis) == diff --git a/src/org/torproject/onionoo/DateTimeHelper.java b/src/org/torproject/onionoo/DateTimeHelper.java new file mode 100644 index 0000000..f97c8c5 --- /dev/null +++ b/src/org/torproject/onionoo/DateTimeHelper.java @@ -0,0 +1,57 @@ +/* Copyright 2014 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.onionoo; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; + +public class DateTimeHelper { + + public static final String ISO_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + public static final String ISO_DATETIME_TAB_FORMAT = + "yyyy-MM-dd\tHH:mm:ss"; + + public static final String ISO_YEARMONTH_FORMAT = "yyyy-MM"; + + public static final String YEARHOUR_NOSPACE_FORMAT = "yyyy-MM-dd-HH"; + + private static Map<String, DateFormat> dateFormats = + new HashMap<String, DateFormat>(); + + private static DateFormat getDateFormat(String format) { + DateFormat dateFormat = dateFormats.get(format); + if (dateFormat == null) { + dateFormat = new SimpleDateFormat(format); + dateFormat.setLenient(false); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + dateFormats.put(format, dateFormat); + } + return dateFormat; + } + + public static String format(long millis, String format) { + return getDateFormat(format).format(millis); + } + + public static String format(long millis) { + return format(millis, ISO_DATETIME_FORMAT); + } + + public static long parse(String string, String format) { + try { + return getDateFormat(format).parse(string).getTime(); + } catch (ParseException e) { + return -1L; + } + } + + public static long parse(String string) { + return parse(string, ISO_DATETIME_FORMAT); + } +} + diff --git a/src/org/torproject/onionoo/DetailsDocumentWriter.java b/src/org/torproject/onionoo/DetailsDocumentWriter.java index 0fd47c5..57d0877 100644 --- a/src/org/torproject/onionoo/DetailsDocumentWriter.java +++ b/src/org/torproject/onionoo/DetailsDocumentWriter.java @@ -1,6 +1,5 @@ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -9,7 +8,6 @@ import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeSet;
import org.apache.commons.lang.StringEscapeUtils; @@ -101,9 +99,6 @@ public class DetailsDocumentWriter implements DescriptorListener, }
private void updateRelayDetailsFiles() { - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); for (String fingerprint : this.newRelays) {
/* Generate network-status-specific part. */ @@ -124,10 +119,10 @@ public class DetailsDocumentWriter implements DescriptorListener, (addressesWritten++ > 0 ? "," : "") + """ + orAddress.toLowerCase() + """); } - String lastSeen = dateTimeFormat.format(entry.getLastSeenMillis()); - String firstSeen = dateTimeFormat.format( + String lastSeen = DateTimeHelper.format(entry.getLastSeenMillis()); + String firstSeen = DateTimeHelper.format( entry.getFirstSeenMillis()); - String lastChangedOrAddress = dateTimeFormat.format( + String lastChangedOrAddress = DateTimeHelper.format( entry.getLastChangedOrAddress()); String running = entry.getRunning() ? "true" : "false"; int dirPort = entry.getDirPort(); @@ -302,9 +297,6 @@ public class DetailsDocumentWriter implements DescriptorListener, }
private void updateBridgeDetailsFiles() { - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); for (String fingerprint : this.newBridges) {
/* Generate network-status-specific part. */ @@ -314,8 +306,8 @@ public class DetailsDocumentWriter implements DescriptorListener, continue; } String nickname = entry.getNickname(); - String lastSeen = dateTimeFormat.format(entry.getLastSeenMillis()); - String firstSeen = dateTimeFormat.format( + String lastSeen = DateTimeHelper.format(entry.getLastSeenMillis()); + String firstSeen = DateTimeHelper.format( entry.getFirstSeenMillis()); String running = entry.getRunning() ? "true" : "false"; String address = entry.getAddress(); diff --git a/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java b/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java index 3c67aea..aa245dc 100644 --- a/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java +++ b/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java @@ -2,7 +2,6 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -11,7 +10,6 @@ import java.util.Scanner; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet;
@@ -289,12 +287,8 @@ public class NodeDetailsStatusUpdater implements DescriptorListener, String fingerprint = descriptor.getFingerprint(); DetailsStatus detailsStatus = this.documentStore.retrieve( DetailsStatus.class, false, fingerprint); - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setLenient(false); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String publishedDateTime = - dateTimeFormat.format(descriptor.getPublishedMillis()); + DateTimeHelper.format(descriptor.getPublishedMillis()); if (detailsStatus != null) { String detailsString = detailsStatus.documentString; String descPublishedLine = ""desc_published":"" @@ -313,7 +307,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener, s.close(); } StringBuilder sb = new StringBuilder(); - String lastRestartedString = dateTimeFormat.format( + String lastRestartedString = DateTimeHelper.format( descriptor.getPublishedMillis() - descriptor.getUptime() * 1000L); int bandwidthRate = descriptor.getBandwidthRate(); int bandwidthBurst = descriptor.getBandwidthBurst(); @@ -377,12 +371,8 @@ public class NodeDetailsStatusUpdater implements DescriptorListener, String fingerprint = descriptor.getFingerprint(); DetailsStatus detailsStatus = this.documentStore.retrieve( DetailsStatus.class, false, fingerprint); - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setLenient(false); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String publishedDateTime = - dateTimeFormat.format(descriptor.getPublishedMillis()); + DateTimeHelper.format(descriptor.getPublishedMillis()); String poolAssignmentLine = null; if (detailsStatus != null) { String detailsString = detailsStatus.documentString; @@ -401,7 +391,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener, s.close(); } StringBuilder sb = new StringBuilder(); - String lastRestartedString = dateTimeFormat.format( + String lastRestartedString = DateTimeHelper.format( descriptor.getPublishedMillis() - descriptor.getUptime() * 1000L); int advertisedBandwidth = Math.min(descriptor.getBandwidthRate(), Math.min(descriptor.getBandwidthBurst(), diff --git a/src/org/torproject/onionoo/NodeStatus.java b/src/org/torproject/onionoo/NodeStatus.java index afe2ed3..1c3983e 100644 --- a/src/org/torproject/onionoo/NodeStatus.java +++ b/src/org/torproject/onionoo/NodeStatus.java @@ -2,18 +2,15 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.SortedSet; import java.util.SortedMap; -import java.util.TimeZone; -import java.util.TreeSet; +import java.util.SortedSet; import java.util.TreeMap; +import java.util.TreeSet;
import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; @@ -126,9 +123,6 @@ public class NodeStatus extends Document { int orPort = -1, dirPort = -1; Boolean recommendedVersion = null; try { - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String separator = documentString.contains("\t") ? "\t" : " "; String[] parts = documentString.trim().split(separator); isRelay = parts[0].equals("r"); @@ -161,8 +155,12 @@ public class NodeStatus extends Document { } else { address = addresses; } - lastSeenMillis = dateTimeFormat.parse(parts[4] + " " + parts[5]). - getTime(); + lastSeenMillis = DateTimeHelper.parse(parts[4] + " " + parts[5]); + if (lastSeenMillis < 0L) { + System.err.println("Parse exception while parsing node status " + + "line '" + documentString + "'. Skipping."); + return null; + } orPort = Integer.parseInt(parts[6]); dirPort = Integer.parseInt(parts[7]); relayFlags = new TreeSet<String>(); @@ -189,13 +187,23 @@ public class NodeStatus extends Document { } firstSeenMillis = lastSeenMillis; if (parts.length > 16) { - firstSeenMillis = dateTimeFormat.parse(parts[15] + " " - + parts[16]).getTime(); + firstSeenMillis = DateTimeHelper.parse(parts[15] + " " + + parts[16]); + if (firstSeenMillis < 0L) { + System.err.println("Parse exception while parsing node status " + + "line '" + documentString + "'. Skipping."); + return null; + } } lastChangedAddresses = lastSeenMillis; if (parts.length > 18 && !parts[17].equals("null")) { - lastChangedAddresses = dateTimeFormat.parse(parts[17] + " " - + parts[18]).getTime(); + lastChangedAddresses = DateTimeHelper.parse(parts[17] + " " + + parts[18]); + if (lastChangedAddresses < 0L) { + System.err.println("Parse exception while parsing node status " + + "line '" + documentString + "'. Skipping."); + return null; + } } if (parts.length > 19) { aSNumber = parts[19]; @@ -212,11 +220,6 @@ public class NodeStatus extends Document { + "status line '" + documentString + "': " + e.getMessage() + ". Skipping."); return null; - } catch (ParseException e) { - System.err.println("Parse exception while parsing node status " - + "line '" + documentString + "': " + e.getMessage() + ". " - + "Skipping."); - return null; } catch (Exception e) { /* This catch block is only here to handle yet unknown errors. It * should go away once we're sure what kind of errors can occur. */ @@ -260,9 +263,6 @@ public class NodeStatus extends Document { }
public String toString() { - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd\tHH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); StringBuilder sb = new StringBuilder(); sb.append(this.isRelay ? "r" : "b"); sb.append("\t" + this.nickname); @@ -280,7 +280,8 @@ public class NodeStatus extends Document { + exitAddress); } } - sb.append("\t" + dateTimeFormat.format(this.lastSeenMillis)); + sb.append("\t" + DateTimeHelper.format(this.lastSeenMillis, + DateTimeHelper.ISO_DATETIME_TAB_FORMAT)); sb.append("\t" + this.orPort); sb.append("\t" + this.dirPort + "\t"); written = 0; @@ -299,10 +300,12 @@ public class NodeStatus extends Document { } else { sb.append("\t-1\t??\tnull\t-1\tnull\tnull"); } - sb.append("\t" + dateTimeFormat.format(this.firstSeenMillis)); + sb.append("\t" + DateTimeHelper.format(this.firstSeenMillis, + DateTimeHelper.ISO_DATETIME_TAB_FORMAT)); if (this.isRelay) { - sb.append("\t" + dateTimeFormat.format( - this.getLastChangedOrAddress())); + sb.append("\t" + DateTimeHelper.format( + this.getLastChangedOrAddress(), + DateTimeHelper.ISO_DATETIME_TAB_FORMAT)); sb.append("\t" + (this.aSNumber != null ? this.aSNumber : "null")); } else { sb.append("\tnull\tnull\tnull"); diff --git a/src/org/torproject/onionoo/ResponseBuilder.java b/src/org/torproject/onionoo/ResponseBuilder.java index 1412d88..73ce683 100644 --- a/src/org/torproject/onionoo/ResponseBuilder.java +++ b/src/org/torproject/onionoo/ResponseBuilder.java @@ -3,7 +3,6 @@ package org.torproject.onionoo;
import java.io.PrintWriter; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -14,7 +13,6 @@ import java.util.Scanner; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeMap;
public class ResponseBuilder { @@ -114,12 +112,9 @@ public class ResponseBuilder { currentBridges.add(node); } } - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - newRelaysPublishedString = dateTimeFormat.format( + newRelaysPublishedString = DateTimeHelper.format( relaysLastValidAfterMillis); - newBridgesPublishedString = dateTimeFormat.format( + newBridgesPublishedString = DateTimeHelper.format( bridgesLastPublishedMillis); List<String> orderRelaysByConsensusWeight = new ArrayList<String>(); for (NodeStatus entry : currentRelays) { diff --git a/src/org/torproject/onionoo/UptimeDocumentWriter.java b/src/org/torproject/onionoo/UptimeDocumentWriter.java index 5b03153..c53c709 100644 --- a/src/org/torproject/onionoo/UptimeDocumentWriter.java +++ b/src/org/torproject/onionoo/UptimeDocumentWriter.java @@ -2,12 +2,10 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeSet;
public class UptimeDocumentWriter implements FingerprintListener, @@ -257,12 +255,9 @@ public class UptimeDocumentWriter implements FingerprintListener, double factor = 1.0 / 999.0; int count = lastNonNullIndex - firstNonNullIndex + 1; StringBuilder sb = new StringBuilder(); - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); sb.append(""" + graphName + "":{" - + ""first":"" + dateTimeFormat.format(firstDataPointMillis) - + "","last":"" + dateTimeFormat.format(lastDataPointMillis) + + ""first":"" + DateTimeHelper.format(firstDataPointMillis) + + "","last":"" + DateTimeHelper.format(lastDataPointMillis) + "","interval":" + String.valueOf(dataPointInterval / 1000L) + ","factor":" + String.format(Locale.US, "%.9f", factor) + ","count":" + String.valueOf(count) + ","values":["); diff --git a/src/org/torproject/onionoo/UptimeStatus.java b/src/org/torproject/onionoo/UptimeStatus.java index 4d8dca7..0eb9dde 100644 --- a/src/org/torproject/onionoo/UptimeStatus.java +++ b/src/org/torproject/onionoo/UptimeStatus.java @@ -2,11 +2,8 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Scanner; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeSet;
class UptimeHistory @@ -36,14 +33,9 @@ class UptimeHistory } else if (!parts[0].equals("b")) { return null; } - long startMillis = -1L; - SimpleDateFormat dateHourFormat = new SimpleDateFormat( - "yyyy-MM-dd-HH"); - dateHourFormat.setLenient(false); - dateHourFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - try { - startMillis = dateHourFormat.parse(parts[1]).getTime(); - } catch (ParseException e) { + long startMillis = DateTimeHelper.parse(parts[1], + DateTimeHelper.YEARHOUR_NOSPACE_FORMAT); + if (startMillis < 0L) { return null; } int uptimeHours = -1; @@ -57,12 +49,9 @@ class UptimeHistory
public String toString() { StringBuilder sb = new StringBuilder(); - SimpleDateFormat dateHourFormat = new SimpleDateFormat( - "yyyy-MM-dd-HH"); - dateHourFormat.setLenient(false); - dateHourFormat.setTimeZone(TimeZone.getTimeZone("UTC")); sb.append(this.relay ? "r" : "b"); - sb.append(" " + dateHourFormat.format(this.startMillis)); + sb.append(" " + DateTimeHelper.format(this.startMillis, + DateTimeHelper.YEARHOUR_NOSPACE_FORMAT)); sb.append(" " + String.format("%d", this.uptimeHours)); return sb.toString(); } diff --git a/src/org/torproject/onionoo/WeightsDocumentWriter.java b/src/org/torproject/onionoo/WeightsDocumentWriter.java index 9e5355f..6e225f1 100644 --- a/src/org/torproject/onionoo/WeightsDocumentWriter.java +++ b/src/org/torproject/onionoo/WeightsDocumentWriter.java @@ -2,7 +2,6 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -11,7 +10,6 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone;
public class WeightsDocumentWriter implements FingerprintListener, DocumentWriter { @@ -183,12 +181,9 @@ public class WeightsDocumentWriter implements FingerprintListener, double factor = ((double) maxValue) / 999.0; int count = lastNonNullIndex - firstNonNullIndex + 1; StringBuilder sb = new StringBuilder(); - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); sb.append(""" + graphName + "":{" - + ""first":"" + dateTimeFormat.format(firstDataPointMillis) - + "","last":"" + dateTimeFormat.format(lastDataPointMillis) + + ""first":"" + DateTimeHelper.format(firstDataPointMillis) + + "","last":"" + DateTimeHelper.format(lastDataPointMillis) + "","interval":" + String.valueOf(dataPointInterval / 1000L) + ","factor":" + String.format(Locale.US, "%.9f", factor) + ","count":" + String.valueOf(count) + ","values":["); diff --git a/src/org/torproject/onionoo/WeightsStatus.java b/src/org/torproject/onionoo/WeightsStatus.java index 4d92f30..93f3087 100644 --- a/src/org/torproject/onionoo/WeightsStatus.java +++ b/src/org/torproject/onionoo/WeightsStatus.java @@ -1,13 +1,10 @@ package org.torproject.onionoo;
-import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.SortedMap; -import java.util.TimeZone; import java.util.TreeMap;
class WeightsStatus extends Document { @@ -23,52 +20,46 @@ class WeightsStatus extends Document { new HashMap<String, Integer>();
public void fromDocumentString(String documentString) { - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setLenient(false); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - try { - Scanner s = new Scanner(documentString); - while (s.hasNextLine()) { - String line = s.nextLine(); - String[] parts = line.split(" "); - if (parts.length == 2) { - String descriptorDigest = parts[0]; - int advertisedBandwidth = Integer.parseInt(parts[1]); - this.advertisedBandwidths.put(descriptorDigest, - advertisedBandwidth); - continue; - } - if (parts.length != 9) { - System.err.println("Illegal line '" + line + "' in weights " + Scanner s = new Scanner(documentString); + while (s.hasNextLine()) { + String line = s.nextLine(); + String[] parts = line.split(" "); + if (parts.length == 2) { + String descriptorDigest = parts[0]; + int advertisedBandwidth = Integer.parseInt(parts[1]); + this.advertisedBandwidths.put(descriptorDigest, + advertisedBandwidth); + continue; + } + if (parts.length != 9) { + System.err.println("Illegal line '" + line + "' in weights " + "status file. Skipping this line."); - continue; - } - if (parts[4].equals("NaN")) { - /* Remove corrupt lines written on 2013-07-07 and the days - * after. */ - continue; - } - long validAfterMillis = dateTimeFormat.parse(parts[0] - + " " + parts[1]).getTime(); - long freshUntilMillis = dateTimeFormat.parse(parts[2] - + " " + parts[3]).getTime(); - long[] interval = new long[] { validAfterMillis, - freshUntilMillis }; - double[] weights = new double[] { - Double.parseDouble(parts[4]), - Double.parseDouble(parts[5]), - Double.parseDouble(parts[6]), - Double.parseDouble(parts[7]), - Double.parseDouble(parts[8]) }; - this.history.put(interval, weights); + continue; + } + if (parts[4].equals("NaN")) { + /* Remove corrupt lines written on 2013-07-07 and the days + * after. */ + continue; + } + long validAfterMillis = DateTimeHelper.parse(parts[0] + " " + + parts[1]); + long freshUntilMillis = DateTimeHelper.parse(parts[2] + " " + + parts[3]); + if (validAfterMillis < 0L || freshUntilMillis < 0L) { + System.err.println("Could not parse timestamp while reading " + + "weights status file. Skipping."); + break; } - s.close(); - } catch (ParseException e) { - System.err.println("Could not parse timestamp while reading " - + "weights status file. Skipping."); - e.printStackTrace(); + long[] interval = new long[] { validAfterMillis, freshUntilMillis }; + double[] weights = new double[] { + Double.parseDouble(parts[4]), + Double.parseDouble(parts[5]), + Double.parseDouble(parts[6]), + Double.parseDouble(parts[7]), + Double.parseDouble(parts[8]) }; + this.history.put(interval, weights); } + s.close(); }
public String toDocumentString() { @@ -77,14 +68,11 @@ class WeightsStatus extends Document { this.advertisedBandwidths.entrySet()) { sb.append(e.getKey() + " " + String.valueOf(e.getValue()) + "\n"); } - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); for (Map.Entry<long[], double[]> e : history.entrySet()) { long[] fresh = e.getKey(); double[] weights = e.getValue(); - sb.append(dateTimeFormat.format(fresh[0]) + " " - + dateTimeFormat.format(fresh[1])); + sb.append(DateTimeHelper.format(fresh[0]) + " " + + DateTimeHelper.format(fresh[1])); for (double weight : weights) { sb.append(String.format(" %.12f", weight)); } diff --git a/src/org/torproject/onionoo/WeightsStatusUpdater.java b/src/org/torproject/onionoo/WeightsStatusUpdater.java index 79296d3..3438325 100644 --- a/src/org/torproject/onionoo/WeightsStatusUpdater.java +++ b/src/org/torproject/onionoo/WeightsStatusUpdater.java @@ -2,7 +2,6 @@ * See LICENSE for licensing information */ package org.torproject.onionoo;
-import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -10,7 +9,6 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet;
@@ -282,8 +280,6 @@ public class WeightsStatusUpdater implements DescriptorListener, new TreeMap<long[], double[]>(history.comparator()); long lastStartMillis = 0L, lastEndMillis = 0L; double[] lastWeights = null; - SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String lastMonthString = "1970-01"; for (Map.Entry<long[], double[]> e : history.entrySet()) { long startMillis = e.getKey()[0], endMillis = e.getKey()[1]; @@ -300,7 +296,8 @@ public class WeightsStatusUpdater implements DescriptorListener, } else { intervalLengthMillis = 10L * 24L * 60L * 60L * 1000L; } - String monthString = dateTimeFormat.format(startMillis); + String monthString = DateTimeHelper.format(startMillis, + DateTimeHelper.ISO_YEARMONTH_FORMAT); if (lastEndMillis == startMillis && ((lastEndMillis - 1L) / intervalLengthMillis) == ((endMillis - 1L) / intervalLengthMillis) &&