jantimon
jantimon

Reputation: 38140

GoogleCalendar Datekey

Google is using an unique DateKeys for each days in the GoogleCalendar HTML e.g.

<div 
  data-datekey="129"
  role="gridcell" 
  tabindex="-1" 
  jsname="RjPD4e" 
  aria-labelledby="tsc-0" 
  data-column-index="0"  
  data-principal-ids="amFuLm5pY2tsYXNAbmFtaWNzLmNvbQ" 
  class="YvjgZe Qbfsob">

Is there any formular to calculate the date for a given datekey?

Upvotes: 6

Views: 302

Answers (2)

pyrocrasty
pyrocrasty

Reputation: 787

In response to @jantimon's answer: I guess they had to do a lot of calculations with dates and wanted it to be efficient.

The odd thing is that if you look at the little calendar in the sidebar, rather than using a data-datekey attribute, it uses data-date with a YYYYMMDD format.

Anyway, I rewrote your conversion function using bitwise operations, since it's easier to read this way.

function datekeyToDate(key) {
    /* # BITS: [year_rel(6)][month(4)][day(5)] */
    const day = key & 0b11111;
    const month = (key>>5) & 0b1111;
    const year_rel = (key>>9);
    const year = 1970 + year_rel;
    return new Date(year, month, day);
}

function dateToDatekey(date) {
    const y = date.getFullYear() - 1970;
    const m = date.getMonth()+1;    /* getMonth() returns 0-based index */
    const d = date.getDate();
    return (y<<9) + (m<<5) + d;
}

Upvotes: 8

jantimon
jantimon

Reputation: 38140

It looks like the dateKey represents the days since 1.1.1970 in a format optimised for byte shifting.

One year has 2^9 (512) days. One month has 2^5 (32) days.

To calculate the datekey for 01.01.1970 you would calculate:

0 years (since 1970) * 512
+ 1 month * 32
+ 1 day
= 33

To calculate the datekey for 01.01.2000 you would calculate:

30 years (since 1970) * 512
+ 1 month * 32
+ 1 day
= 15393

To calculate the date for a given date key you can do the opposite. A modulo calculation could look like the following:

function getDate(dateKey) {
  const yearOffset = (dateKey - 32) % 512;
  const year = (dateKey - 32 - yearOffset) / 512;
  const day = yearOffset % 32;
  const month = (yearOffset - day) / 32;
  return new Date(year + 1970, month, day);
}

Does anyone know why they came up with such a logic?

Upvotes: 8

Related Questions