« first day (1015 days earlier)      last day (2165 days later) » 

12:00 AM
'@TestMethod
Public Sub TestMethod1() 'TODO Rename test
    On Error GoTo TestFail

    Fakes.MsgBox.Returns 42
    MsgBox "Is logged"
    Assert.Inconclusive

TestExit:
    Exit Sub
TestFail:
    Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description
End Sub
^Works.
Need to sort out the Verify syntax though.
 
RELOAD!
[Hosch250/Rubberduck] 17 commits. 13187 additions. 18457 deletions.
[retailcoder/Rubberduck] 1 commit. 100 additions. 130 deletions.
[rubberduck-vba/Rubberduck] 16 commits. 4 opened issues. 25 issue comments. 2223 additions. 2199 deletions.
 
@Comintern I think Timer returns a Single, so maybe there's not much better precision available, but if you hook the Timer function, could you make Timer offer better granularity by using GetTickCount or QueryPerfCounter/Stopwatch?
 
Not really. The problem is that whatever RD returns will get marshalled as a Single.
It would be easier to just expose a Rubberduck.Timer.
protected void ThrowVbaError() <-- muahahaha!
 
@Comintern ok that's seriously awesome
 
@Comintern IIUC, Timer is the granularity of the number of seconds since midnight, but I don't know if the minimum tick size is constrained by the granularity of the underlying timer, or the granularity of a Single. Maybe if the hooked function returned the number of integer Ticks (instead of the number of seconds), the decimal part wouldn't matter, or would a Single overflow with number of ticks?
@Comintern Go on, Fake the Assert...
 
12:11 AM
@ThunderFrame I don't think I can. That's wired directly into the kernel's debug APIs.
Maybe we should hook those...
:shudders:
 
@Comintern I meant the Rubberdug.Assert
Fake yourself
 
@ThunderFrame Meh. Trivial.
 
Fake the Faker -> Stack Overflow and boom
 
Although if\when we get real mocks, that is something we'll need to test.
Rubberduck.Mocks.Create Rubberduck.Assert '<---DON'T DO THIS!
2
 
A Single can store a value integer values in the range of -16,777,216 to 16,777,216 without a loss of precision. There 86400 seconds in a day. Seems like there's space in the domain to at least return centiseconds.
 
12:14 AM
Can't mock a class instance yet?
 
Not yet. I'm going to finish up the Fakes first.
OK, so I'm tracking all of the parameters from every call that goes through the fake.
Does this look like a reasonable interface from VBA?
With Fakes.MsgBox.Verify
    .Invocations 2
    .Parameter "prompt", "Hello from SomeSub", 1
    .Parameter "prompt", "Second call", 2
End With
Could be single-lined too: Fakes.MsgBox.Verify.Invocations 2
 
maybe Fakes should always be used in With blocks? Then you know they're destroyed?
 
They're all singletons, and all get destroyed explicitly after each test run.
 
what if @Thunderframe creates a global Fake variable?
 
If you tried to put one in a global or something like that, it would just throw an error if you tried to use it.
 
12:24 AM
@Comintern that's beautiful!
 
@Comintern Going to put it on CR?
 
Yeah, why not. That's a good idea.
 
@ThunderFrame I think the examples in the wiki should hace them in with blocks prominently
 
I was thinking about the file handling stuff this afternoon. We might want to dummy up a fake file system and tie all of them into each other.
 
Sub foo()

  Dim curr As Single
  Dim last As Single
  Dim cnt As Long

  last = Timer

  Do While cnt < 50
    curr = Timer
    If curr > last Then
      Debug.Print last, curr, curr > last
      last = curr
      cnt = cnt + 1
    End If
  Loop

End Sub
 40892.64      40892.64     True
 40892.64      40892.65     True
 40892.65      40892.65     True
 40892.65      40892.66     True
 40892.66      40892.66     True
 40892.66      40892.66     True
 40892.66      40892.67     True
Is that the Debug.Print Format that's inferring that 40892.65 > 40892.65?
 
12:30 AM
Wait... You can do debug.print 1, 2, 3, 4
Another gold nugget gleaned from the RD team.
2
This is why I lurk here all the time now.
 
Huh. Come to think of it, we could enforce a no assignment rule. If there's an assignment of an IFake we could just not run the test and do something like OnAssertDontBeADick.
 
@IvenBach If you liked that, you'll love this:
Debug.Print 1; Tab(25); 2; Spc(14); 3, 4;
Debug.Print 5, 6
Prints:
<markdown fail>
replaces spaces with underscores
_1_______________________2________________3______________4__5__________6
 
@Comintern lol
I think the next RD News blog post title is going to be "It's a mock! It's a fake! It's a duck!" ..something like that.
 
fakes like a duck, ducks like a fake
 
@ThunderFrame That I'll have to remember.
 
12:39 AM
@Comintern any ideas on that Single behavior example above?
 
That looks like rounding to me.
 
In the If statement? Or before that in the assignment?
 
In Debug.Print.
 
but the Debug.Print should never hit
 
The comparison is the raw, unrounded Singles - the Debug.Print would be using a formatter.
 
12:44 AM
42256.20000000000000        42256.21000000000000        True
42256.21000000000000        42256.21000000000000        True
42256.21000000000000        42256.21000000000000        True
42256.21000000000000        42256.22000000000000        True
 
Is it possible that it's implicitly being promoted to a Double then narrowed back to a Single for some unknown VBA reason like backward compatibility?
IIR, the resolution of the API timers has increased several times in the lifespan of VBA.
 
Dim diff As Double
diff = curr - last
If curr > last Then
  Debug.Print Format$(last, f), Format$(curr, f), diff
  last = curr
  cnt = cnt + 1
End If
42336.82000000000000        42336.83000000000000         0.00390625
42336.83000000000000        42336.83000000000000         0.00390625
42336.83000000000000        42336.84000000000000         0.00390625
42336.84000000000000        42336.84000000000000         0.00390625
42336.84000000000000        42336.84000000000000         0.00390625
42336.84000000000000        42336.85000000000000         0.00390625
 
Sometime in 1995: "Oh, we don't need ms resolution. No VB instruction takes less than 10ms to execute."
2
 
@Comintern lol, has a non-zero chance of being the actual truth
 
IKR?
 
12:49 AM
@Comintern Why I feel like that was an actual question?
 
> no one is ever going to need more than 640kb of memory
3
 
#NeverSayNever
 
^ and that probably shows my age lol
 
@Mat'sMug No one is ever going to have more ToolWindows than the VBE
 
I've new up objects that take more than 640kb on a daily basis.
 
12:51 AM
I always forget RAM is now rated in GB.
 
> Rubberduck.Setup.2.0.13.0.exe (5.83 MiB) - Downloaded 195 times.
Last updated on 2017-03-12
> Total Downloads 10,344
 
@Mat'sMug To play Star Wars Tie Fighter, edit HIMEM.SYS you must.
 
~50 a day. Impressive for a small utility tool.
 
@IvenBach I think half of it is the update notification, the other half might be YouTube
 
OK, what's missing?
public interface IVerify
{
    void AtLeast(int invocations);
    void AtLeastOnce();
    void AtMost(int invocations);
    void AtMostOnce();
    void Between(int minimum, int maximum);
    void Exactly(int invocations);
    void Never();
    void Once();
    void Parameter(string parameter, object value, int invocation = 1);
    void ParameterIsPassed(string parameter, int invocation = 1);
    void ParameterIsType(string parameter, string typeName, int invocation = 1);
}
 
12:54 AM
@Mat'sMug Did you ever get the 'My cup holder is broken' scenario?
 
@Comintern I'll have to think about it... Damn it's awesome. Compared with Moq?
@IvenBach huh?
bbiab
 
@Mat'sMug 'Cd-rom drive' != 'Cup holder'
 
@IvenBach I just had to buy a replacement 5.25in floppy drive, as my old one has head damage from reading an old disk.
 
@ThunderFrame @Mat'sMug already killed an issue for that.
 
Floppy's are a great way to store secure information now. Nobody has readers for them.
 
12:59 AM
@Hosch250 That was before Annotations got escalated to first-class object in 3.0
 
K
 
@IvenBach I have a Kryoflux unit. Plug my floppy into my Windows 10 PC with a USB cable.
I don't have a CD on my laptop, but I do have an external drive-box that has 5.25in floppy, 3.5in floppy, DVD RW and a SATA caddy.
 
@ThunderFrame still, I don't think we're going to support xml doc in comments the way .net has them
I like annotations though
And yeah, exporting doc-annotations to xml is definitely a valuable feature I think.
Or heck... export to Microsoft Word document
 
@Mat'sMug Transform to WordML
 
Whatever. The limitations are where we put them!
 
1:18 AM
Code comments should document the why something is done that way. Not what is happening. What is happening should be self evident, correct?
 
^ Yes.
 
I am so SMRT!
Now that makes sense why I hear 'good coders don't need to comment their code' or things similar to that.
 
They should document anything that is non-obvious too.
Here's an example of that:
    //Any time the selected control changes in the hosted userform, the F3 Overlay has to be redrawn.  This is a good proxy
    //for child control selections, so raise a focus event.
    if ((int) msg == (int)WM.ERASEBKGND)
    {
        DispatchFocusEvent(FocusType.GotFocus);
    }
 
@IvenBach except xml-doc / doc-annotations: these babies show up in intellisense, so you want them to describe the what - just not the how.
 
@Mat'sMug I'm not there so I'll still live in my bubble. Your note is being filed away till I understand it better. Do you have an example?
 
1:21 AM
Best CR answer about comments IMO:
113
A: Guessing a number, but comments concerning

rolflWelcome to the hell of comments, and personal taste. There are multiple answers to your core question that may be right: you have not commented enough you have commented all the wrong things you have commented too much. your comments are in the wrong format you are missing the formal comments. ...

 
@Mat'sMug You don't want them to describe the how at all. That is an implementation detail.
 
@Hosch250 that's exactly what I said =)
 
Oh, I read it "not just".
 
@Comintern aye, that looks like the why to me =)
 
That was the counter example - it's non-obvious. ;-)
 
1:25 AM
@IvenBach if you don't write .net or java, just leave it filed until RD supports doc-annotations
 
TBH, I'm glad I put that there because I would have forgotten what it was there for.
 
(or Python, or PHP, or... anything other than VBA)
@Comintern I need to improve on that aspect
 
@Mat'sMug I only write .net code I read directly from a book to follow a tutorial. Other than that I know I'm not qualified unless I've got my RD pool floaties on.
 
cough duck-annotations
 
@IvenBach - The "don't touch this" comments are also usually a good idea:
    //DO NOT REMOVE THIS CALL. Dockable windows are instantiated by the VBE, not directly by RD.  On top of that,
    //since we have to inherit from UserControl we don't have to keep handling window messages until the VBE gets
    //around to destroying the control's host or it results in an access violation when the base class is disposed.
    //We need to manually call base.Dispose() ONLY in response to a WM_DESTROY message.
    _thisHandle = GCHandle.Alloc(this, GCHandleType.Normal);
 
1:28 AM
^ that would be // HERE BE DRAGONS
 
LOL
 
:light bulb: So that's what the 'Here be dragons' comment stuff means, gotcha.
 
Trust me, you know them when you see them.
 
@IvenBach write something that works - anything - and put it up for review on CR; some reviewees claim to have learned more in two weeks than in two years of university
 
I sent a long email the other day describing important system changes. The last paragraph referenced flying unicorns and fire-breathing dragons. Not one person commented.
 
1:31 AM
If you want ideas for something fun to write, look at meta posts tagged
@ThunderFrame did anyone read it up to that last paragraph lol
 
@Mat'sMug I have 0 knowledge in C# and would be like that poster earlier that had -5 vote in 5 mins if I tried to do something C#.
 
It is easier to do it right in C# than VBA.
 
Heading home. Thank you all again for your continued help. I really appreciate it.
@Hosch250 Please don't pop my VBA bubble. I already know it's easier but I'm scared.
 
Fearless you must be, or VBA will win.
4
 
@ThunderFrame LOL - That's funny, I wrote a long email to a marketer the other day explaining how it takes me longer to re-write a query than it takes her to use the damned auto-filter on the spreadsheet I sent.
 
1:33 AM
@IvenBach CR isn't SO. On SO you get downvotes when you can't clearly explain what the problem is. On CR you get downvotes if your code doesn't work or if you ask for help instead of feedback on any/all aspects of the code.
 
@ThunderFrame Eh, I'd at least read the last, even if I skipped the middle.
 
Maybe I need to lead with flying unicorns and fire-breathing dragons.
Something like "tldr; The dragon breaths fire on the unicorn."
2
@Hosch250 That's true on several different levels.
Is it evil to put a string interpolation inside a format call? string.Format(UsageResultFormat, $"{minimum} - {maximum}", _usages.Count, message)
 
Umm, I wouldn't think so.
 
That's probably more intuitive.
 
I've been thinking about the "donate" thing. I think I'll put it up. And then use it to pay for RD swag.
 
1:39 AM
@Comintern nah, I'm keeping it up my sleeve for when they break it, and I'll say "but I told you so"
 
Heather-gray T-shirts and mugs?
You have to have a mug.
Or maybe black T-shirts would show the duck better.
 
I want a rubber duck with the Rubberduck logo on it.
 
Mugs, tees, rubber duckies
 
Eh, Donald Trump (my CR duck) is enough duck for me.
 
Stickers
Whatever
@Comintern we have a logo?
 
1:42 AM
How about a baseball cap to wear to interviews?
You know, I'm thinking maybe I should go for a paid internship.
I have like a 50-75% success getting interviews for internships.
I've had nothing for normal jobs.
 
It's logo-ish.
 
Oh
 
Isn't that a logo?
 
That's more poster-ish ^^
 
Well, you could take the duck out and make a little logo.
 
1:44 AM
The RD News favicon is just "RD"
@Comintern I want that on a t-shirt =)
 
IKR?
 
@Hosch250 and that would look nice on a white mug
 
@Hosch250 That's exactly what I did for the icon refresh. Looked like crap until I downscaled it though - the water is non-trivial to remove with Gimp.
 
I have PSE.
I had to take a PSE course in college for my communications minor.
 
@Comintern lol, I have the layered .pdn file....
but yeah, ducky & water are on the same layer
 
1:47 AM
Seriously? All I could find was the original NASA image.
 
well I made the .pdn off the original...
 
After much copy-paste, internal class Verifier : IVerify is born!
 
@Mat'sMug I have this in AI/EPS/SVG.
and this
 
^ found through google image search of the RD splash screen/"logo"
 
Yo no hablo español
:fires up Google translate:
 
2:01 AM
> This page is in Portuguese. Would you like to translate it to English?
@ThunderFrame lol
 
Apparently I know so little Portuguese I thought it was Spanish. Christ, I feel like the VB.NET askers in the VBA tag.
 
LOL
 
What's this with franchising ideas I'm reading about guys? Am I missing something?
 
@PeterMTaylor Merchandise, not Franshise
 
Woot! 6 more votes until my 2nd Great Answer badge.
 
2:09 AM
#swag
@PeterMTaylor I think I'm cool with a "donate" button, to pay for RD swag =)
 
Cheating: AssertHandler.OnAssertInconclusive("Not implemented.");
 
2:30 AM
@Comintern not crazy at all - although this looks like a nice place to hide an Easter egg
for trying to fake Rubberduck.FakesProvider I mean :)
 
    if (value.GetType() == typeof(AssertClass))
    {
        AssertHandler.OnAssertInconclusive("Don't be ridiculous.");
    }
 
    if (value.GetType() == typeof(IVerify))
    {
        AssertHandler.OnAssertInconclusive("Woah! Meta IVerify.");
    }
 
[rubberduck-vba/Rubberduck] build for commit 2d44b1b1 on unknown branch: AppVeyor build succeeded
 
    if (value.GetType() == typeof(IFake))
    {
        AssertHandler.OnAssertInconclusive("expected: Stack overflow?; actual: Guard clause.");
    }
 
@Comintern niiiiiiiice!
I want them all!!
 
Done. private bool IsEasterEgg(object value)
3
 
Although, I think I'd just put "Nope." instead of the first :)
 
Yeah, the strings are open for discussion. I am partial to "expected: Stack overflow?; actual: Guard clause." though.
 
oh, that one is going verbatim!
they should all follow that pattern nah
    if (value.GetType() == typeof(IVerify))
    {
        AssertHandler.OnAssertInconclusive("IVerify too.");
    }
 
2:44 AM
LOL
 
0
A: for next loop failing to allocate a value to a variable - VBA

ThunderFrameIt seems likely that the values in your ComboBox are numeric Strings, and the values in your ranges are numbers (and you've confirmed the license being 3 numbers). Your code was failing because Cells returns a numeric cell as Variant/Double, and a ComboxBox.Value returns a Variant/String. Compar...

 
Oh, this whole feature has some great Easter egg potential. Remember, we hold an Err object.
 
You're not the Messiah, you're a very naughty boy
 
_errObject.Raise(666, "What the hell do you think you're doing?")
^ Easter egg HeHasRisen?
 
@Comintern I read this and thought "ha, let's hijack error 666"
@Comintern then I saw this
 
2:48 AM
LOL
 
that SO answer - Do we have an inspection for Variant equality operations?
 
nope
 
Speak of the devil, I was just writing one.
 
10 hours ago, by Comintern
The fake callbacks need a custom marshaller - .NET's marshalling chokes on *VARIANT when it's an option parameter that wasn't passed.
 
2:54 AM
[rubberduck-vba/Rubberduck] build for commit 63785c49 on next: AppVeyor build succeeded
 
Can a Combobox.Value be anything other than Variant/String?
 
I don't think so. Pretty sure it's an implicit cast to a String.
 
@Comintern keep the err.number the same vbErrObject (+ 666), but rotate/randomize the err.description?
 
Not exactly sure where to raise that one - I'm currently only using it if validation fails.
We can't throw in a unit test - I'm raising an RD error with the Err object so it gets caught in the unit test's handler.
I really want to hook Debug.Print...
Do we have any ComVisible enums yet?
Crap we do, but they don't follow the VBA naming convention. public enum FileStatus should probably be public enum RdFileStatus
 
3:11 AM
Fakes.MsgBox.Returns 42 With Fakes.MsgBox.Verify .Once .Parameter "prompt", "Rubberduck says hi" End With #VBA is #GettingReal
 
How big a deal would it be to break our COM visible enum interfaces?
 
depends which ones
 
All of them. They really should follow the COM naming convention.
i.e. rdEnumName.
 
right
I'm all for it!
 
Accessibility is a big problem.
OK, I'll open an issue so it doesn't get lost in the release notes after it's merged.
 
3:15 AM
isn't it doubled up in the API namespace?
 
Yep.
 
Accessibility isn't ComVisible outside the API namespace.. I think.. how is it a problem?
 
I could also double them up for internal usage and add an explicit cast between the internal and external for stuff like that.
[ComVisible(true)]
public enum Accessibility
It's used in Declaration, which is COM exposed.
 
hmm
but does it have to be?
 
Yeah - the property returns one.
 
3:20 AM
the property?
I mean Parsing.Symbols.Declaration doesn't need to be COM visible :)
 
public Accessibility Accessibility { get { return (Accessibility)_declaration.Accessibility; } }
 
which namespace is that in?
in Rubberduck.API it returns a Rubberduck.API.Accessibility value
 
It's in Rubberduck.API:
public interface IDeclaration
{
    [ComVisible(true)]
    string Name { get; }
    [ComVisible(true)]
    Accessibility Accessibility { get; }
    [ComVisible(true)]
    DeclarationType DeclarationType { get; }
    string TypeName { get; }
    [ComVisible(true)]
    bool IsArray { get; }
    [ComVisible(true)]
    Declaration ParentDeclaration { get; }
    [ComVisible(true)]
    IdentifierReference[] References { get; }
}
DeclarationType too, but not much room for collision there.
 
yeah all of Rubberduck.API exposed stuff should be per COM rules - I thought you meant the Parsing.Symbols.Accessibility was COM-visible
 
[rubberduck-vba/Rubberduck] retailcoder pushed 29 commits to next (only showing some of them below)
[rubberduck-vba/Rubberduck] retailcoder pushed commit f6ca0777 to next: setup ICodeModule.Clear mock
[retailcoder/Rubberduck] retailcoder pushed 38 commits to rd-next (only showing some of them below)
[retailcoder/Rubberduck] BZngr pushed commit 4bc4fd44 to rd-next: Updated to latest RD/next. Merge remote-tracking branch 'rubberduck-vba/next' into next
 
3:26 AM
@rubberduckvba That is exactly what we need! Well that and source control, but I digress.
 
I should also check to make sure that all of the setters work. COM enum = int, so I'm not sure that the implicit cast is guaranteed to succeed when they come through the Interop layer.
I'm not exactly sure how that works. I've never exposed an enum before.
 
I'd say you can cast any int to any enum
 
Wouldn't that be handled by the marshaller though?
It might just throw back to the external caller.
That would be the ideal, I guess.
 
@ThunderFrame thanks for the correction. Right idea wrong spelling on my side.
@Mat'sMug no worries.
 
@Duga oooh that's nice!
 
What the heck?
var components = GetDeclaration(parameter).Project.VBComponents;
{
    components.Add(ComponentType.StandardModule);
}
Who is responsible for that *?
 
I am. that's from back when I tried to dispose/release everything we touch that deals with a COM wrapper
 
4:14 AM
just remove the braces when you see them
 
:(
 
@Comintern Ooh, #2591
 
> Not only that - it should also add @Folder("VBAProject") in all modules without a @Folder annotation.
> Not only that - we should also add @Folder("VBAProject") in all modules without a @Folder annotation.
[rubberduck-vba/Rubberduck] build for commit 9a41a66b on next: AppVeyor build failed
BUILD FAILURE!
 
@Duga 236 changed files? Time to synch...
 
4:30 AM
wait a minute did I just merge this the wrong way around?
oh shit I did
FCK
 
@Mat'sMug Should new test modules automatically get the VBAProject annotation too?
Just, when they are added from anywhere, I mean.
 
Holy sh!t. I can tell from the hooks if there's been an implicit cast.
 
@Comintern NO WAI
 
Wai.
 
HookInspection
?
 
4:33 AM
3.0 is starting.
4
 
Only works if they're called in a test.
 
aaaah, right
 
niiiice!!
 
protected override void ExecuteImpl(object parameter)
{
    _newUnitTestModuleCommand.Execute(parameter != null
        ? GetDeclaration(parameter).Project
        : _vbe.ActiveVBProject);
}
Somehow, that needs a second parameter--folder.
 
4:37 AM
make an overload / add an optional parameter?
 
Can't--it is a command.
It doesn't matter anyway.
They are all automatically added to the Tests folder.
#ReadTheCode
So, that should be adjustable in the settings.
But, not a problem at the moment.
@Mat'sMug The folder annotation works with or without quotations.
I'm using with quotations just because I'm lazy.
 
only if you don't have spaces
better be consistent and use the quotes all the time
 
Yeah.
 
What level of experience would be required to read a CSV file into C# and have it it be shown in WPF. Remember I have near no knowledge.
 
@IvenBach Not much.
 
4:44 AM
about near no knowledge ;-)
 
The hardest part will be getting the WPF bindings right.
Get over your imposter syndrome.
 
As long as I'm not at an interview, I have an attitude that I'm an up-and-coming Eric Lippert ;)
 
The binding is the <TextBlock Text="{Binding SomeName}" /> portion?
 
> RenameTests: 26 passed
 
4:45 AM
@IvenBach Nuget is your friend. CsvHelper #DontReinventTheWheel
 
Yeah. If you have that down, it shouldn't be an issue.
 
I'm not trying to reinvent anything. I'm just trying to learn the basics. Reading the WPF book alone isn't getting me much progress so I'm going to trying and couple my desire to learn with gaming to make more progress.
 
CSV parsing is not trivial.
You can import libraries that do the grunt work and then focus on the WPF aspect of it.
 
I can bruteforce it via Excel, like I've always done. But I need to learn how to do it automatidly so I can do the conversions I want on many files.
 
Excel will mangle CSV with cell formatting. ;-)
 
4:53 AM
just don't count on Excel creating CSV that's reliable
3
 
RD CSV is rock solid not under test, but works
 
@Mat'sMug Got any ideas to DRY those three up a bit?
 
[Hosch250/Rubberduck] Hosch250 pushed commit baf48e53 to Issue2884: Close #2884
 
4:55 AM
From VBA, I almost always us ADO and the ACE text driver for importing CSV - it's much more reliable.
 
but meh, RD Clipboard gives you SpreadsheetML for use in Excel and RTF for use in Word, so CSV can BIAF
 
I've got GetDeclaration and GetFolder in those three files.
 
extract an interface and compose a new dependency?
 
[rubberduck-vba/Rubberduck] Hosch250 review_requested pull request #2886: Close #2884
 
I don't know...
 
I'd rather have an abstract base class AddComponent that implemented them.
 

« first day (1015 days earlier)      last day (2165 days later) »