So, I finally decided to dig into the code and see what's causing this. It turns out to be a one-line bug in the StackExchange.user.initRepGraphs()
function.
Specifically, at the top of this function, there's a loop that tries to "massage the data into a format that highcharts will like". One part of this is converting a (year / month / day) tuple into milliseconds since January 1, 1970, 00:00:00, UTC. (It does need to be UTC, since the subsequent date formatting code expects UTC, as does the Ajax back-end that returns the rep change events.)
Unfortunately, the code does this incorrectly, by calling new Date(...).getTime()
instead of Date.UTC(...)
. The difference between these two methods is that new Date(...)
assumes the input date/time values to be in local time, rather than UTC, and so the resulting timestamps will be offset from midnight by the user's local time zone offset.
This bug doesn't have any visible effects for users in time zones west of UTC (such as the U.S.), since their timestamps will just be some hours later than they should be, and they'll get silently rounded down to midnight anyway. But for us poor folks living in mainland Europe or Asia (or Africa or Australia, etc.), the timestamps will be some hours early, and will therefore fall on the previous day.
Anyway, here's a patch (unified context diff) against the internal 01_rep-graph.js
file, as extracted from the user.en.js
file linked above:
--- 01_rep-graph.orig.js 2016-01-09 20:07:12.706406358 +0200
+++ 01_rep-graph.edit.js 2016-01-09 20:08:27.871033685 +0200
@@ -15,7 +15,7 @@
var d = rawData[i];
// Date.UTC(year, month, day), where month is 0-11.. INSANITY!
- var date = new Date(d[0], d[1] - 1, d[2]).getTime(),
+ var date = Date.UTC(d[0], d[1] - 1, d[2]),
realRep = d[3],
rep = Math.max(realRep, -50); // cap the negative bar at -50
Note that, curiously, the comment just before the broken line mentions the correct Date.UTC()
method. Perhaps this code used to be correct, until some well-intentioned editor broke it?
Anyway, could someone at SE please apply this patch?
Ps. I've also developed a partial JS hotfix for this bug:
$.ajaxPrefilter( function( options ) {
var re = /^(\/ajax\/users\/\d+\/rep\/day\/)(\d+)([\/?#].*)?$/;
var m = re.exec( options.url );
if (!m) return;
var t = 1*m[2], day = 24*60*60, offset = t % day;
if (2*offset > day) offset -= day;
options.url = m[1] + (t - offset) + m[3];
} );
Running this code in the browser JS console should make clicking the rep graph load the rep events for the correct day. The code fixes the Ajax requests for rep events by rounding the timestamp to the nearest midnight UTC, rather than down to the previous midnight as the server effectively does. Alas, it still won't fix the incorrect dates in the tooltips.
This hotfix will be part of the next SOUP release, unless the bug is fixed by SE in the mean time, of course. Impatient folks can already grab it from the SOUP development branch.
graph
tab, but to see reputation changes viapost
ortime
tabs.