[Question]
  [
### Introduction
This challenge is inspired by the Meta Stack Exchange question [The longest consecutive days streak](https://meta.stackexchange.com/q/362489/295232); it turns out that the URL `https://codegolf.stackexchange.com/users/daily-site-access/[user id]`, where the last number is your user ID (found in the URL of your profile) contains information about which days you visited the site, in the following format:
```
var visited = {2015:{6:{3:1,8:1,12:1,13:1,18:1,19:1,21:1,22:1,23:1,24:1,26:1},7:{7:1,8:1,9:1,10:1,11:1,12:1,14:1,16:1,19:1,21:1,23:1,27:1,28:1,29:1,30:1},8:{1:1,2:1,3:1,5:1,7:1,17:1,19:1,23:1,26:1,28:1,30:1},9:{5:1,6:1,7:1,14:1,22:1,25:1,29:1,30:1},10: ...
```
(When viewed in a browser, the document seems empty; try viewing the source instead. Unless you are a ♦ moderator, you can only see this information for your own account.)
The string has a rather peculiar format but presumably it's an easy way to populate the calendar:
[![enter image description here](https://i.stack.imgur.com/l2hIR.png)](https://i.stack.imgur.com/l2hIR.png)
The information can be used to calculate the longest consecutive days streak, i.e. the one that determines if you get the [Fanatic badge](https://codegolf.stackexchange.com/help/badges/23/fanatic). The linked question has a working JavaScript example by user @ShadowWizard.
Standard [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") rules apply: the shortest code wins.
### Input
A string with the exact format provided by Stack Exchange, e.g. `{2015:{6:{3:1}}}`. Top level keys are years, second level keys are months, third level keys are days. All values are `1`. You may assume the dates are not earlier than July 31st, 2008, which is when the [first Stack Overflow question](https://stackoverflow.com/questions/1/where-oh-where-did-the-joel-data-go) was posted. You may also assume there's at least one day in the input; the information is only provided to registered users, who must have visited the site at least once.
### Output
The length of the longest streak, i.e. consecutive days in the input. You may choose to return it as a number or a string.
### Test cases
(besides your own streak on CGCC of course; you should be able to verify if you're eligible for the Enthusiast and Fanatic badges or not)
| Input | Output |
| --- | --- |
| `{2015:{6:{3:1}}}` | 1 |
| `{2015:{6:{3:1}},2016:{6:{3:1}}}` | 1 |
| `{2015:{6:{3:1},7:{3:1}}}` | 1 |
| `{2015:{6:{3:1,5:1}}}` | 1 |
| `{2015:{6:{3:1,4:1}}}` | 2 |
| `{2015:{2:{28:1},3:{1:1}}}` | 2 |
| `{2016:{2:{28:1},3:{1:1}}}` | 1 |
| `{2016:{1:{30:1},2:{1:1}}}` | 1 |
| `{2016:{4:{30:1},5:{1:1}}}` | 2 |
| `{2016:{4:{30:1},6:{1:1}}}` | 1 |
| `{2016:{12:{31:1}},2017:{1:{1:1}}}` | 2 |
| `{2016:{12:{31:1}},2018:{1:{1:1}}}` | 1 |
| `{2016:{11:{29:1},12:{30:1,31:1}},2017:{1:{1:1,2:1,4:1}}}` | 4 |
| `{2100:{2:{28:1},3:{1:1}}}` | 2 |
| `{2400:{2:{28:1},3:{1:1}}}` | 1 |
 
  
[Answer]
# [Python 2](https://docs.python.org/2/), ~~186 184 179 177 173 172~~ 162 bytes
-10 thanks to [ovs](https://codegolf.stackexchange.com/users/64121/ovs)! (avoiding use of `.items`)
```
x=input()
from datetime import*
a=sorted(date(y,m,d)for y in x for m in x[y]for d in x[y][m])
print max(map(len,`[d+timedelta(1)in a for d in a*2]`.split('s')))/6
```
**[Try it online!](https://tio.run/##PY1hC4MgEIa/9yv8ljbZOhuNCf2SCBI0JqRJOUik3950sMEd9773vMe54F@LZee5d9q6t8ekmNbFICm88toopI1bVl8VotvSVBJnggM1VJJpWVFA2qIdZWm@sg9DNvJnejOQwq3aemTEjo1weFaWjr285AdSzV5gICkt0P9QVGwYr5ubtcflVhJCbu15RlZDyyMAj@zJ4aDAeGxqDrSBZA@a@CPxXEBZ6nteHx8 "Python 2 – Try It Online")** Or see the [test-suite](https://tio.run/##hZDhaoMwFIV/16cI7IdJFzYTre2EPkknNDQpDRgVmzFF@uzupkNXu2qDYC7nu@fk3rKxpyLn3aGQauv7/mdXb3VefllMvGNVGCSFVVYbhbQpi8ouPbE9w19J7BTcUEMlORYVapDOUY3c1VyvuyZ1heyLnUmJV1Y6t8iIGhtR4kzldL@Try5AqswKzAjQAg2NYsnT/du5zLTF/tknhLzHHbzT@z7pTCGWeAiOqtUBuxFI1/KArZI2TtowYZfLZeHOC1ow706hUMZ34AOOrucBupqLodFI5b3K4ds49zBp2a37LxHPEKwnGCQEjuBTRNQTq6mUgYgnU8A9ZP3C1tfYgby1GoObf@CfIwj8w4VeWyCePgiAqfrtQXMEzSwIniwumiXGIz2PhaZF9AM "Python 2 – Try It Online").
### Huh, how?
In Python 2 `input` implicitly attempts an `eval` on the string which, in this case, will produce a nested dictionary.
`a` is then a list of the dates in order (`sorted(...)`), this is formed by inspecting the nested dictionaries in a nested `for` loop, and passing the resulting parts of the dates to `date(year, month, day)`.
`[d+timedelta(1)in a for d in a*2]` forms a list of `boolean`s which identify whether the next date is present for each date in the sorted dates repeated twice, `a*2`.
Note that the final value of `a` will always be `False`. The reason for repeating `a` is to avoid something later (see the final paragraph).
``[...]`` gets the Python string representation (AKA `repr`) of that list - for example, something like `"[False, True, True, False, False, False, True, True, False, False]"` for an input with three consecutive dates between two others.
`.split('s')` splits the resulting string at occurrences of the `'s'` character - so for the above, that would be `['[Fal', 'e, True, True, Fal', 'e, Fal', 'e, Fal', 'e, True, True, Fal', 'e, Fal', 'e]']`.
`map(len,...)` simply gives us a list of the lengths of the strings in the above list - so for the above, that would be `[4, 18, 6, 6, 18, 6, 2]`.
`max(...)` gives the maximum value of that list - so for the above, that would be `18`.
To find the number of consecutive days we want to count how many `True`s there were in that longest section and then add one. In the above example, we can simply divide by six (the length of either `'True, '` or `'e, Fal'`), hence the `/6` at the end.
If the longest run of consecutive dates is at the left of the sorted dates we'd get something like `'[True, True, Fal'` (or `'[Fal'` when no dates at all are consecutive), which would be two shy of what we need, so if we were to perform all of this across `a` rather than `a*2` we'd need to add two before performing the integer division (e.g. `(...+2)/6`). This wouldn't affect any other results but costs one more byte than simply repeating `a` with `a*2`, whereupon we'll get the longer string later on - this is guaranteed by the fact that `d+timedelta(1)` for the maximal `d` will give `False`.
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~45~~ 43 bytes
*Thanks to [Jonathan Allan](https://codegolf.stackexchange.com/users/53748/jonathan-allan) for pointing out a mistake, now corrected.*
```
j':1?'0YXU2e"@Y:wXHx2e"H@Y:g3$YO]]vtf-FT#XM
```
[Try it online!](https://tio.run/##y00syfn/P0vdytBe3SAyItQoVckh0qo8wqMCyPIAMtONVSL9Y2PLStJ03UKUI3z//682MjA0s6o2NLSqNrK0MqzVMTSyqjY2sDLUMTYEcmt1gPLmQHkQMtQxAmITkHAtAA) Or [verify all test cases](https://tio.run/##y00syfmf8D9L3crQXt0gMiLUKFXJIdKqPMKjAsjyADLTjVUi/WNjy0rSdN1ClCN8/7uE/K82MjA0tao2s6o2tjKsra3lQhPQAXLNcMvrmGOX0DHFJmiCImgERBYgM4ytqg0RMmb4ZAyBBhmAZIzQZUxgMqY4ZcwwTAOaYmwI86Y52Hh8KiywqQCKGFmCjAerBVqkg8VIoHuRvG9oYIDDkybYZQA).
### How it works
```
j         % Input as (unevaluated) string
':1?'     % Push this string. Will be interpreted as regexp
0         % Push 0. Will be interpreted as character 0 (equivalent to space)
YX        % Regexprep: replace ':' or ':1' by character 0
U         % Evaluate string. Gives nested cell array
2e        % Reshape as a 2D cell array with 2 rows (in column major order)
"         % For each column. Each column contains a year and a (nested) cell array
  @       %   Push current column, as a cell array
  Y:      %   Unbox: pushes year, then the cell array
  w       %   Swap
  XHx     %   Copy to clipboard H and delete
  2e      %   Reshape cell array as a 2D cell array with 2 rows 
  "       %   For each column. Each column contains month and a cell array (of days)
    H     %     Push year from clipboard
    @     %     Push current column, as a cell array
    Y:    %     Unbox: pushes month, then the cell array of days
    g     %     Convert cell array to numerical vector of days
    3$YO  %     3-input datenum: converts year, month, days to serial date numbers
  ]       %   End
]         % End
v         % Concatenate stack into numerical vector of serial date numbers
tf        % Duplicate, find. Gives vector of the same size containing 1, 2, 3...   
-         % Subtract, element-wise
FT#XM     % Second output of mode function: number of repetitions of the mode
          % Implicit display
```
[Answer]
# JavaScript (ES6), 122 bytes
*Thanks to @tsh for a bug fix and some optimizations*
```
o=>(D=k=1,M=g=(o,c)=>Object.keys(o).map(c))(o,y=>g(Y=o[y],m=>g(Y[m],d=>M>(D-(D=Date.UTC(y,m-1,d))<-1e8?k=1:++k)?0:M=k)))|M
```
[Try it online!](https://tio.run/##rdNNT4MwGMDxu59ixzZ7YJS3IbHs4K7Eix7MsgNCtzjGurjFhCCfHR9YWGIErArhACH8eP6h3UXv0Sl@ez2etYNMRLXhleQBWfKUMwj5lhMJMeXBw8tOxGc9FfmJSKpn0ZHElOLDnAdb8szlKl9D1lyvsjUkPAhR0RBaRmehPz3ekxwyjUFC6Z3GhLfAD/jTaUoXhh/ylFL6EVaxPJzkXuh7uSUbUpgGc/zC9QvLZ2VZThQPSiez2YTdDGqAt64KrqLBXHVGBQ0c5VoVzf6lZnZrJp5enWr5BVMh@zX3zxrr1hiWGrVmjqHZreaMUXrV3FFKsdBi7fqdN@mD6uBsXzVPVeubDd82b@vUxsVo6BgV/1G7Ji@a/U1jhjHierP/of24s@q9CggDdgMz@uSLZlWf "JavaScript (Node.js) – Try It Online")
### Commented
```
o => (                  // o = input object
  D =                   // D = previous day, as an integer
  k = 1,                // k = streak length
  M =                   // M = maximum streak length
  g = (o, c) =>         // g is a helper function which applies a callback
  Object.keys(o).map(c) // function c to each key of an object o
)(                      // 1st call to g with ...
  o,                    //   ... the input object o
  y =>                  //   for each year y,
  g(                    //   do a 2nd call to g with ...
    Y = o[y],           //     ... the object of months o[y]
    m =>                //     for each month m,
    g(                  //     do a 3rd call to g with ...
      Y[m],             //       ... the object of days Y[m]
      d =>              //       for each day d,
      M > (             //       test whether M is greater than the updated k
        D - (           //         subtract from D ...
          D = Date.UTC( //         ... the new D corresponding to
            y, m - 1, d //         this year, this month and this day
          )             //       
        ) < -1e8 ?      //         if the difference is less than -10**8 ms:
          k = 1         //           reset k to 1
        :               //         else:
          ++k           //           increment k
      ) ?               //       if M is greater than the new value of k:
        0               //         do nothing
      :                 //       else:
        M = k           //         update M to k
    )                   //     end of 3rd call
  )                     //   end of 2nd call
) | M                   // end of 1st call; return M
```
]