Fixed timezone offset trouble:

- Day by Day graph no longer applies timezone offset twice
- MySQL no longer applies timezone offset on its own
  (Connections set timezone to UTC)
- Server calendar possibly fixed
This commit is contained in:
Rsl1122 2019-09-23 18:38:32 +03:00
parent 68a2c3b571
commit 2139067ac5
9 changed files with 72 additions and 29 deletions

View File

@ -119,14 +119,12 @@ public class GraphJSONParser {
); );
return "{\"uniquePlayers\":" + return "{\"uniquePlayers\":" +
lineGraphs.lineGraph(MutatorFunctions.toPointsWithRemovedOffset( lineGraphs.lineGraph(MutatorFunctions.toPoints(
MutatorFunctions.addMissing(uniquePerDay, TimeUnit.DAYS.toMillis(1L), 0), MutatorFunctions.addMissing(uniquePerDay, TimeUnit.DAYS.toMillis(1L), 0)
timeZone
)).toHighChartsSeries() + )).toHighChartsSeries() +
",\"newPlayers\":" + ",\"newPlayers\":" +
lineGraphs.lineGraph(MutatorFunctions.toPointsWithRemovedOffset( lineGraphs.lineGraph(MutatorFunctions.toPoints(
MutatorFunctions.addMissing(newPerDay, TimeUnit.DAYS.toMillis(1L), 0), MutatorFunctions.addMissing(newPerDay, TimeUnit.DAYS.toMillis(1L), 0)
timeZone
)).toHighChartsSeries() + )).toHighChartsSeries() +
'}'; '}';
} }
@ -144,14 +142,12 @@ public class GraphJSONParser {
); );
return "{\"uniquePlayers\":" + return "{\"uniquePlayers\":" +
lineGraphs.lineGraph(MutatorFunctions.toPointsWithRemovedOffset( lineGraphs.lineGraph(MutatorFunctions.toPoints(
MutatorFunctions.addMissing(uniquePerDay, TimeUnit.DAYS.toMillis(1L), 0), MutatorFunctions.addMissing(uniquePerDay, TimeUnit.DAYS.toMillis(1L), 0)
timeZone
)).toHighChartsSeries() + )).toHighChartsSeries() +
",\"newPlayers\":" + ",\"newPlayers\":" +
lineGraphs.lineGraph(MutatorFunctions.toPointsWithRemovedOffset( lineGraphs.lineGraph(MutatorFunctions.toPoints(
MutatorFunctions.addMissing(newPerDay, TimeUnit.DAYS.toMillis(1L), 0), MutatorFunctions.addMissing(newPerDay, TimeUnit.DAYS.toMillis(1L), 0)
timeZone
)).toHighChartsSeries() + )).toHighChartsSeries() +
'}'; '}';
} }

View File

@ -68,8 +68,7 @@ public class CalendarFactory {
) { ) {
return new ServerCalendar( return new ServerCalendar(
uniquePerDay, newPerDay, playtimePerDay, sessionsPerDay, uniquePerDay, newPerDay, playtimePerDay, sessionsPerDay,
formatters.iso8601NoClockLong(), formatters.timeAmount(), theme, locale, formatters.iso8601NoClockLong(), formatters.timeAmount(), theme, locale
config.getTimeZone()
); );
} }
} }

View File

@ -25,7 +25,6 @@ import com.djrapitops.plan.settings.theme.ThemeVal;
import java.util.Map; import java.util.Map;
import java.util.NavigableMap; import java.util.NavigableMap;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TimeZone;
/** /**
* Utility for creating FullCalendar calendar event array on Player page. * Utility for creating FullCalendar calendar event array on Player page.
@ -43,7 +42,6 @@ public class ServerCalendar {
private final Formatter<Long> timeAmountFormatter; private final Formatter<Long> timeAmountFormatter;
private final Theme theme; private final Theme theme;
private final Locale locale; private final Locale locale;
private final TimeZone timeZone;
ServerCalendar( ServerCalendar(
SortedMap<Long, Integer> uniquePerDay, SortedMap<Long, Integer> uniquePerDay,
@ -53,8 +51,7 @@ public class ServerCalendar {
Formatter<Long> iso8601Formatter, Formatter<Long> iso8601Formatter,
Formatter<Long> timeAmountFormatter, Formatter<Long> timeAmountFormatter,
Theme theme, Theme theme,
Locale locale, Locale locale
TimeZone timeZone
) { ) {
this.uniquePerDay = uniquePerDay; this.uniquePerDay = uniquePerDay;
this.newPerDay = newPerDay; this.newPerDay = newPerDay;
@ -64,7 +61,6 @@ public class ServerCalendar {
this.playtimePerDay = playtimePerDay; this.playtimePerDay = playtimePerDay;
this.theme = theme; this.theme = theme;
this.locale = locale; this.locale = locale;
this.timeZone = timeZone;
} }
public String toCalendarSeries() { public String toCalendarSeries() {
@ -77,7 +73,6 @@ public class ServerCalendar {
} }
private void appendTimeZoneOffsetData(StringBuilder series) { private void appendTimeZoneOffsetData(StringBuilder series) {
// Has a timezone offset
appendUniquePlayers(series); appendUniquePlayers(series);
appendNewPlayers(series); appendNewPlayers(series);
appendSessionCounts(series); appendSessionCounts(series);
@ -92,7 +87,7 @@ public class ServerCalendar {
} }
Long key = entry.getKey(); Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC String day = iso8601Formatter.apply(key);
series.append(",{\"title\": \"").append(locale.get(HtmlLang.NEW_CALENDAR)).append(" ").append(newPlayers) series.append(",{\"title\": \"").append(locale.get(HtmlLang.NEW_CALENDAR)).append(" ").append(newPlayers)
.append("\",\"start\":\"").append(day) .append("\",\"start\":\"").append(day)
@ -109,7 +104,7 @@ public class ServerCalendar {
} }
Long key = entry.getKey(); Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC String day = iso8601Formatter.apply(key);
series.append(",{\"title\": \"").append(locale.get(HtmlLang.UNIQUE_CALENDAR)).append(" ").append(uniquePlayers) series.append(",{\"title\": \"").append(locale.get(HtmlLang.UNIQUE_CALENDAR)).append(" ").append(uniquePlayers)
.append("\",\"start\":\"").append(day) .append("\",\"start\":\"").append(day)
@ -125,7 +120,7 @@ public class ServerCalendar {
continue; continue;
} }
Long key = entry.getKey(); Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC String day = iso8601Formatter.apply(key);
series.append(",{\"title\": \"").append(locale.get(HtmlLang.LABEL_PLAYTIME)).append(": ").append(timeAmountFormatter.apply(playtime)) series.append(",{\"title\": \"").append(locale.get(HtmlLang.LABEL_PLAYTIME)).append(": ").append(timeAmountFormatter.apply(playtime))
.append("\",\"start\":\"").append(day) .append("\",\"start\":\"").append(day)
@ -141,7 +136,7 @@ public class ServerCalendar {
continue; continue;
} }
Long key = entry.getKey(); Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC String day = iso8601Formatter.apply(key);
series.append(",{\"title\": \"").append(locale.get(HtmlLang.SIDE_SESSIONS)).append(": ").append(sessionCount) series.append(",{\"title\": \"").append(locale.get(HtmlLang.SIDE_SESSIONS)).append(": ").append(sessionCount)
.append("\",\"start\":\"").append(day) .append("\",\"start\":\"").append(day)

View File

@ -39,6 +39,7 @@ import javax.inject.Singleton;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -140,9 +141,16 @@ public class MySQLDB extends SQLDB {
} }
} }
if (connection.getAutoCommit()) connection.setAutoCommit(false); if (connection.getAutoCommit()) connection.setAutoCommit(false);
setTimezoneToUTC(connection);
return connection; return connection;
} }
private void setTimezoneToUTC(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
statement.execute("set time_zone = '+00:00'");
}
}
@Override @Override
public void close() { public void close() {
super.close(); super.close();

View File

@ -130,7 +130,7 @@ public class PlayerCountQueries {
* @param before Before epoch ms * @param before Before epoch ms
* @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping. * @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping.
* @param serverUUID UUID of the Plan server * @param serverUUID UUID of the Plan server
* @return Map: Epoch ms (Accuracy of a day) - How many unique players played that day * @return Map: Epoch ms (Start of day at 0 AM, no offset) - How many unique players played that day
*/ */
public static Query<NavigableMap<Long, Integer>> uniquePlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<NavigableMap<Long, Integer>> uniquePlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
@ -172,7 +172,7 @@ public class PlayerCountQueries {
* @param after After epoch ms * @param after After epoch ms
* @param before Before epoch ms * @param before Before epoch ms
* @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping. * @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping.
* @return Map: Epoch ms (Accuracy of a day) - How many unique players played that day * @return Map: Epoch ms (Start of day at 0 AM, no offset) - How many unique players played that day
*/ */
public static Query<NavigableMap<Long, Integer>> uniquePlayerCounts(long after, long before, long timeZoneOffset) { public static Query<NavigableMap<Long, Integer>> uniquePlayerCounts(long after, long before, long timeZoneOffset) {
return database -> { return database -> {
@ -288,7 +288,7 @@ public class PlayerCountQueries {
* @param before Before epoch ms * @param before Before epoch ms
* @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping. * @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping.
* @param serverUUID UUID of the Plan server * @param serverUUID UUID of the Plan server
* @return Map: Epoch ms (Accuracy of a day) - How many new players joined that day * @return Map: Epoch ms (Start of day at 0 AM, no offset) - How many new players joined that day
*/ */
public static Query<NavigableMap<Long, Integer>> newPlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<NavigableMap<Long, Integer>> newPlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
@ -324,6 +324,14 @@ public class PlayerCountQueries {
}; };
} }
/**
* Fetch a EpochMs - Count map of new players on a server.
*
* @param after After epoch ms
* @param before Before epoch ms
* @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping.
* @return Map: Epoch ms (Start of day at 0 AM, no offset) - How many new players joined that day
*/
public static Query<NavigableMap<Long, Integer>> newPlayerCounts(long after, long before, long timeZoneOffset) { public static Query<NavigableMap<Long, Integer>> newPlayerCounts(long after, long before, long timeZoneOffset) {
return database -> { return database -> {
Sql sql = database.getSql(); Sql sql = database.getSql();

View File

@ -439,6 +439,15 @@ public class SessionQueries {
}; };
} }
/**
* Query session count for each day within range on a server.
*
* @param after After epoch ms
* @param before Before epoch ms
* @param timeZoneOffset Offset in ms to determine start of day.
* @param serverUUID UUID of the Plan server.
* @return Map - Epoch ms (Start of day at 0 AM, no offset) : Session count of that day
*/
public static Query<NavigableMap<Long, Integer>> sessionCountPerDay(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<NavigableMap<Long, Integer>> sessionCountPerDay(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
Sql sql = database.getSql(); Sql sql = database.getSql();
@ -539,6 +548,15 @@ public class SessionQueries {
}; };
} }
/**
* Query playtime for each day within range on a server.
*
* @param after After epoch ms
* @param before Before epoch ms
* @param timeZoneOffset Offset in ms to determine start of day.
* @param serverUUID UUID of the Plan server.
* @return Map - Epoch ms (Start of day at 0 AM, no offset) : Playtime of that day
*/
public static Query<NavigableMap<Long, Long>> playtimePerDay(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<NavigableMap<Long, Long>> playtimePerDay(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
Sql sql = database.getSql(); Sql sql = database.getSql();

View File

@ -130,6 +130,25 @@ function lineChart(id, series) {
})); }));
} }
function dayByDay(id, series) {
graphs.push(Highcharts.stockChart(id, {
rangeSelector: {
selected: 2,
buttons: linegraphButtons
},
yAxis: {
softMax: 2,
softMin: 0
},
title: {text: ''},
legend: {
enabled: true
},
time: {timezoneOffset: 0},
series: series
}));
}
function onlineActivityCalendar(id, events, firstDay) { function onlineActivityCalendar(id, events, firstDay) {
$(id).fullCalendar({ $(id).fullCalendar({
eventColor: '#2196F3', eventColor: '#2196F3',

View File

@ -891,7 +891,7 @@
name: s.name.newPlayers, type: s.type.spline, tooltip: s.tooltip.zeroDecimals, name: s.name.newPlayers, type: s.type.spline, tooltip: s.tooltip.zeroDecimals,
data: data.newPlayers, color: v.colors.newPlayers data: data.newPlayers, color: v.colors.newPlayers
}; };
lineChart('uniqueChart', [uniquePlayers, newPlayers]); dayByDay('uniqueChart', [uniquePlayers, newPlayers]);
} else if (error) { } else if (error) {
$('#uniqueChart').text("Failed to load graph data: " + error) $('#uniqueChart').text("Failed to load graph data: " + error)
} }

View File

@ -1547,7 +1547,7 @@
name: s.name.newPlayers, type: s.type.spline, tooltip: s.tooltip.zeroDecimals, name: s.name.newPlayers, type: s.type.spline, tooltip: s.tooltip.zeroDecimals,
data: data.newPlayers, color: v.colors.newPlayers data: data.newPlayers, color: v.colors.newPlayers
}; };
lineChart('uniqueChart', [uniquePlayers, newPlayers]); dayByDay('uniqueChart', [uniquePlayers, newPlayers]);
} else if (error) { } else if (error) {
$('#uniqueChart').text("Failed to load graph data: " + error) $('#uniqueChart').text("Failed to load graph data: " + error)
} }