Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Days getting shifted? #126

Closed
kedarv opened this issue Jan 8, 2015 · 6 comments
Closed

Days getting shifted? #126

kedarv opened this issue Jan 8, 2015 · 6 comments

Comments

@kedarv
Copy link

kedarv commented Jan 8, 2015

Hi,
For some reason, the heatmap is shifting some of the JSON values. I don't think this is related to timezone because all of my events (recorded in EST) occur before 11pm (viewing in central time zone). I suspect that everything is shifted back one day.

I did some debugging, and found that I have the following events on sunday:
Sun 17 @ 1408233600
Sun 7 @ 1410048000
Sun 14 @ 1410652800
Sun 5 @ 1412467200
Sun 9 @ 1415491200

However, the heatmap graphs a lot of sunday events (last row is sunday). I know for sure that the data generated by my backend is correct.
capture

I'm not sure why this is happening. Can someone give me some guidance?


<script type="text/javascript">
    $(".message").slideUp(700);
    $(".visualization").fadeIn(1200);
    var cal = new CalHeatMap();
    cal.init({
        itemSelector: "#cal-heatmap",
        domain: "month",
        subDomain: "day",
        domainDynamicDimension: true,
        domainGutter: 0,
        data: {"1408233600":1,"1408320000":2,"1408492800":1,"1408579200":2,"1408665600":1,"1408752000":2,"1408924800":3,"1409011200":3,"1409184000":1,"1409270400":1,"1409356800":1,"1409529600":1,"1409616000":1,"1409702400":2,"1409788800":1,"1409875200":1,"1409961600":1,"1410048000":1,"1410134400":1,"1410220800":1,"1410307200":2,"1410393600":1,"1410480000":1,"1410652800":1,"1410739200":1,"1410912000":2,"1411084800":3,"1411344000":1,"1411516800":1,"1411689600":1,"1411948800":1,"1412121600":1,"1412208000":1,"1412294400":1,"1412467200":1,"1412553600":1,"1412726400":1,"1412899200":1,"1413331200":1,"1413504000":1,"1413763200":1,"1413849600":1,"1413936000":1,"1414022400":1,"1414108800":1,"1414195200":1,"1414368000":1,"1414454400":1,"1414540800":1,"1414713600":1,"1414972800":1,"1415059200":1,"1415145600":1,"1415232000":1,"1415318400":1,"1415491200":1,"1415577600":1,"1415664000":1,"1415750400":1,"1415836800":1,"1416182400":2,"1416268800":1,"1416355200":1,"1416528000":1,"1416787200":1,"1417392000":1,"1417478400":1,"1417564800":1,"1417651200":1,"1417737600":1,"1417824000":3,"1417996800":1,"1418083200":1,"1418169600":1,"1418256000":1,"1418342400":1,"1418601600":1,"1418688000":1,"1418774400":1,"1418860800":1,"1418947200":1},
        dataType: "json",
        start: new Date(2014, 0),
        cellSize: 12,
        range: 12,
        legend: [1],
        legendColors: ["#2E2E2E", "#E3AE24"],
        onClick: function(date, nb) {
            $("#onClick-placeholder").html("You just clicked <br/>on <b>" +
                date + "</b> <br/>with <b>" +
                (nb === null ? "unknown" : nb) + "</b> items"
                );
        },      
        label: {
            position: "bottom",
            align: "center",
        }
    });
</script>
@benhutchins
Copy link

benhutchins commented Oct 13, 2015

I was seeing this same issue in Gitlab and was able to determine it was based on the user's timestamp, when converting a timestamp that is at midnight (example 1372791600) by doing new Date(1372791600 * 1000) you will get a date that has the difference that is your the timezone of your browser client.

My data for example had 1372791600, my server provided this with UTC time, my browser was set to EDT (Eastern Daylight Time) which is -0400 so when I do just:

new Date(1413158400 * 1000);
// Sun Oct 12 2014 20:00:00 GMT-0400 (EDT)

Should have returned Mon, 13 Oct 2014 00:00:00 +0000 (see here).

This is no good, because the contributions calendar Gitlab uses is a daily thing, it means all dates will appear to be off by one day, because what should have been Monday Oct 13th at midnight became Sunday Oct 2 at 20:00.

So if your server does not consider the user's timezone, which is probably won't, then your client needs to.

I fixed this with an afterLoadData function

afterLoadData: function (timestamps) {
  var offset = new Date().getTimezoneOffset() * 60
  var results = {}
  for (var timestmap in timestamps) {
    var commitCount = timestamps[timestamp]
    timestmap = parseInt(timestmap, 10)
    results[timestamp + offset] = commitCount
  })
  return results
}

@Luiz-N
Copy link

Luiz-N commented Nov 15, 2016

solid answer @benhutchins ... this issue could/should be closed @wa0x6e

@kedarv kedarv closed this as completed Nov 15, 2016
@pydanny
Copy link

pydanny commented Dec 7, 2016

Lovely answer @benhutchins, and it saved my sanity. However, there are a few bugs in your code snippet. This is my corrected version, which I'm putting here for convenience:

afterLoadData: function (timestamps) {
  var offset = new Date().getTimezoneOffset() * 60;
  var results = {};
  for (var timestamp in timestamps) {
    var commitCount = timestamps[timestamp];
    timestamp = parseInt(timestamp, 10);
    console.log(timestamp)
    results[timestamp + offset] = commitCount;
  };
  return results;
}

Again, thanks so much for providing the original answer. 😄

@voidsteed
Copy link

Thanks for the solution, @benhutchins and @pydanny! There is an additional issue with this solution. I'm in EST timezone, and there is daylight saving time(EDT) change on every March 12th. So when you do offset calculation in EDT time, the dates before March 12th is shift back one day. and there will be a missing date on March 12 in my project. At that time I would rather to use 5-hour-offset instead of 4-hour-offset.

@sergeysolovev
Copy link

@voidsteed @benhutchins @pydanny

Hey guys, thanks for your help!

I've updated afterLoadData based on the comment from @voidsteed and this SO answer

const afterLoadData = timestamps => {
  const stdTimezoneOffset = date => {
    const jan = new Date(date.getFullYear(), 0, 1);
    const jul = new Date(date.getFullYear(), 6, 1);
    return Math.max(
      jan.getTimezoneOffset(),
      jul.getTimezoneOffset()
    );
  };
  const offset = stdTimezoneOffset(new Date()) * 60;
  let results = {};
  for (let timestamp in timestamps) {
    const value = timestamps[timestamp];
    timestamp = parseInt(timestamp, 10);
    results[timestamp + offset] = value;
  };
  return results;
}

P.S.: It's ES6, but you can easily update it to be ES5

@kevinhooke
Copy link

Lovely answer @benhutchins, and it saved my sanity. However, there are a few bugs in your code snippet. This is my corrected version, which I'm putting here for convenience:

afterLoadData: function (timestamps) {
  var offset = new Date().getTimezoneOffset() * 60;
  var results = {};
  for (var timestamp in timestamps) {
    var commitCount = timestamps[timestamp];
    timestamp = parseInt(timestamp, 10);
    console.log(timestamp)
    results[timestamp + offset] = commitCount;
  };
  return results;
}

Again, thanks so much for providing the original answer. 😄

I have been debugging this issue for a while and wish I'd found this issue earlier :-) The issue I'm seeing is that the offset from utc appears to be (24 - my timezone offset), so for PST -8, I need to add 24-8 hours. Not sure why yet or if I've done something else which has contributed to the issue, but this afterLoadData and adding 24-8hrs is a working workaround for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants