Converting to JavaScript.

I'd like to have control over the generated JavaScript, because I'd like to make
it as small as possible.

My experience with minifying JavaScript so far has shown me that the only thing
that makes it smaller is removing logic. `gzip` is so efficient that it doesn't
matter so much if you're verbose, using long names, or fiddly constructs. You
wouldn't save four bytes everywhere if the `function` keyword was replaced with
`func`.

Converting from objects as JSON to arrays, for example, doesn't give you as much
savings as you'd imagine after `gzip`, because `gzip` is going to eliminate the
heft of the object key names, so long as they are redundant.

Thus, I'm pretty sure that I could have a small program with CoffeeScript. If
CoffeeScript is more verbose at times, using boilerplate for testing against
both `undefined` and `null`, `gzip` will smash it up good. It looks heavy, but
it is a common construct, repeated frequently, and it gets squished.

If I'm still interested in demonstrating the viability of CoffeeScript later on,
it is easier to convert from JavaScript to CoffeeScript. Once I have a tiny
JavaScript library, I can come back and see how much it grows when converted to
CoffeeScript.

In the mean time, I really want to see what I'm doing, so I can learn what sort
of JavaScript makes for micro JavaScript.

I'm going to start by adding my CoffeeScript generated JavaScript. This commit
will add the JavaScript, the next commit will de-dent it, then I'll start to
convert the code a function at a time, into hand-crafted JavaScript.

Here's where I'm at now with file size.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          33014/32.24 12395/12.10  7304/07.13  4921/04.81
Deleting `Cakefile`.

Before I forget and obliterate a lot of work with a reflexive `cake Compile`,
I'm going to delete the `Cakefile` and add the `.gitignore` it generates to
the `git` repository.
Dedent generated JavaScript.

Got the JavaScript reasonably de-dented. Doing this as a single commit so that
no changes are lost in a sea of whitespace changes.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          29122/28.44 12255/11.97  7059/06.89  4845/04.73
Unify varargs. Shorter days in month, leap year.

Unified variable argument functions. They no longer create a `splat` variable.
In all cases where a `splat` variable was created, it was passed onto another
function, so we just invoke `Array.prototype.slice` directly in the arguments of
the function call.

Using JavaScript `Date` to determine last day of month and leap year. When I
first wrote the library, I wasn't ready to trust `Date` to do the right thing.
It does do the right thing. It works all the way back to IE 6.

Some additional code tidy; changes to the declaration style of some functions,
foratting some JavaScript object literals.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          28195/27.53 11966/11.69  6923/06.76  4777/04.67
Fixed zone table scope.

Including a timezone rule set table would make that rule set table visible to
any instance of the `tz` function, not just a newly created partial function.
This was because I was not copying the new timezone rule set table into the
request, which is the context of a new partial definition. I was copying it into
the context, which would expose it to the `tz` function used to create the
partial function.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          28244/27.58 11984/11.70  6927/06.76  4780/04.67
Tidy of `convert`.

General tidy of `convert`, mostly to remove CoffeeScript array iteration so I
can see what's going on.

Changed one test of `indexOf` to use bitwise negation of the result, which is
the style I prefer.

The `adjustments` array does not need to be part of the `request` object. It can
be a local variable and as such, it can get minified.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          28066/27.41 11911/11.63  6931/06.77  4733/04.62
Tidy of `zoneinfo`.

Another concentrated tidy of a function that's messy with CoffeeScript array
iteration. Removed the CoffeeScript array iteration. Changed the signature of
`zoneinfo` to accpet just the `zones` object and the the entire `request`.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          27926/27.27 11891/11.61  6887/06.73  4724/04.61
Remove closure around adjust, tidy helpers.

Changed the function declaration style of the `append` and `extend` helpers.
Tidies the loop in `extend`, removing unnecessary local variables.

Removed the closure from around adjust exposing it and all its helpers in the
scope of the module definition closure. This is an initial step before further
rewriting, so that significant changes are not lost the diffs due to in
whitespace changes.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          27973/27.32 11831/11.55  6925/06.76  4732/04.62
Remove closures surrouding `parse` and `format`.

Removed the closures surrounding `parse` and `format`. This ought to be the last
de-denting commit for a while.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          27184/26.55 11783/11.51  6854/06.69  4738/04.63
Smaller implementation of `adjustment`.

Couple of modifications to make date math require less code.

Simplified the date math language. Not as many synonyms. Not as many literals in
the code.

Building the regular expression from a string. Using the string that defines the
alternation that matches the time units to create a lookup table to determine
which unit was matched by the regular expression. No need to express the
language keywords in two different forms.

Using `Date` to do year, month, and date math, instead of incrementing and
carrying an array of integer values for year, month, date. Less logic means less
code which means less size.

Using `parseInt` to determine the sign matched by the regular expression instead
of a lookup object.

Eliminated variables, inlining some arithmetic. Less variables is less size.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          24955/24.37 11158/10.90  6371/06.22  4479/04.37
Reject `Date`. No arguments means now.

No longer accepting `Date` as a valid time value. Convert to POSIX time before
calling, please.

No arguments returns the value of the clock. Use `tz()` instead of `tz(tz.now)`.
Thus, to get the current year, `tz(tz(), "%Y")`. Closes #18.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          24785/24.20 11128/10.87  6359/06.21  4445/04.34
Remove `actualize` for now. Tidy timezone lookup.

Tidy timezone lookup somewhat. The CoffeeScript generated JavaScript was already
pretty well formatted.

Removing `actualize` for now. It is an old implementation of the function that
is not currently used. When we do get back around to actualizing the tables as
needed, we're going to use a newer, smaller implementation from
`lib/transitions.js`.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          22340/21.82 10070/09.83  5928/05.79  4065/03.97
Limit date parsing to RFC 3999.

Fortunately, there is such a thing as RFC 3999 that defines the reasonable
subset of ISO 8601 that we tend to use. This way, we don't have to say that we
parse a subset ISO 8601, we can say instead that we parse the entirety of RFC
3999. The RFC 3999 explains the reasons for using a subset of ISO 8601 with
authority. We are not saddle with the burden of explanation.

Nor do we have to bloat the library with absurd date formats that no one will
ever use, so that we can say that we parse 8601 without caveats. No one will
ever want to parse a date with week number and day of week, but if we don't
parse it, we can't make a succinct statement about our date string formats
relationship to this standard.

I'd not actually read RFC 3999. I knew that it supported using a space in place
of the `T` to make the date slightly more legible. I didn't realize it defined a
subset. If someone had asked me, I might have said that it was merely an
extension that permitted the space.

I'm happy that it is a well reasoned subset. The discussion in RFC 3999 is as
good a discussion of the experiences of storing time as strings as any I've
encountered so far. It will be cited in the landing page for this library.

I doubt that I'll bother with ISO 8601 myself. If someone wants to write an ISO
8601 parser, they can do date math to navigate by days of the year and weeks.

Also, ISO 8601 is only half about date formats. The rest of it is about
durations and intervals, which is beyond the scope of my interest in computer
storage of dates and times for this lifetime.

The RFC 3999 date parser correctly parses timezone offsets, so it closes #8.

The RFC 3999 date parser correctly parses a full date accounting for the
timezone, converting from wall-clock time to POSIX time. No conversion according
to timezone is performed if a timezone offset is specified explicitly in the
date string, either by timezone offset or by using the letter `Z` to indicate
`UTC`.

The timezone aware parsing us closer to closing issue #3, but we still need to
test the determination of an implicit date.

No longer parsing RFC 822. Moved the code off to the side. Will either make it a
pluggable parser, or a parser that parses RFC 822 and turns it into RFC 3999
for use by `tz`.

Better still, an RFC 822 parser can emit the intermediate array format that the
RFC 3999 parser internal to `tz` emits.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          18934/18.49  8762/08.56  5173/05.05  3599/03.51
Tidy of `format`.

Attaching the padding size to the date formatting function as an object property
so I don't have to keep a separate object to use as a map of format specifiers
to padding sizes. Attaching the style and padding properties to the formatting
function will make it easier to split a set of the formatting specifiers out
into an extension.

The regular expression that matches format strings is now built from a string
using format specifiers gathered the specifier map. This regular expression is
rebuilt when new format specifiers are added. One more step to splitting up
formatting into basic and extended.

We're going to split foramtting into basic and extended. Basic foramtting is
anything numeric that does not require a mess of calculation. Extended
formatting will include the day of year, week of year, and localized format
specifiers.

The day of year and week of year calculations are not a common use case, and the
week of year functions are rather hefty at the moment.

Localization means asynchronously loading locale JSON, which is by its nature,
something extra. There are use cases for this library where it is doing
calculations without localization strings, such as logging, where the basic
formatting can still create human readable strings, provided that human is a
system administrator.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          19223/18.77  8927/08.72  5204/05.08  3613/03.53
Object prototype for inheritance.

Instead of copying the properties from one context to the next, we'll be using
prototypical inheritance going forward. We can use one object to store all the
properties, for the same reason we can plop any arguments into our call to `tz`,
because the different properties are distinct characteristics.

Locales always five characters with an underscore, we'll know zone information
because a rule set will exist, and format specifiers are always a single
character.

We're able to express the overwrite behavior of the `convert` function more
succinctly. When an argument is specified in the argument list, it overwrites
the property of the newly created list. Before it the logic was convoluted, one
argument list overwriting another, that was untested, and probably didn't work.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          18391/17.96  8540/08.34  5026/04.91  3460/03.38
Break full GNU `date` out into `date.js`.

Locale support is hefty. If you want a little you get a lot, so if you really
don't want a lot, you're going to not want any. When you do want locale support,
you can have it, along with week of year, and day of year, with a single
additional library.

The `date.js` library is a formatting extension library for the `tz` function
that implements all of the rest of GNU `date`.

Made `weekOfYear` a little smaller by removing some unnecessary local variables.

Also, I found found a bug I'd left in my tests. Math across daylight savings
time clock transitions was displaying the correct timezone offset, but the wrong
timezone acronym. At the time I wrote the test, I was about to reimplement
timezones lookup, so I made the broken output the fixture. Left a `TODO` and
everything.

Now it's fixed.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          11988/11.71  5500/05.37  3464/03.38  2415/02.36
    date.js                   4591/04.48  3077/03.00  1256/01.23  1034/01.01
Fix array date creation and test it.

Creating a date from an array of integer field values, where the integers are
integers or their string representations. This is the same logic used internally
to build a milliseconds since the epoch offset from a parsed RFC 3999 date
string, so the `tz` function can consume the output of other date parsers that
create this array of integers format.

The array of integers format includes a capacity for zone offsets, treating the
three digits after either a `'-'` or `'+'` character as the hours, minutes and
seconds of a timezone offset. The sign character is used to determine the sign
of the offset.

If there are fewer than five numbers before a sign, then it is assumed that the
date portion of the date was not specified, only the time. If this is case, then
the year, month, and date of the applicable timezone according to the applicable
clock is used to complete the date.

This method of specifying a date is for use with other date parsers, or UI
controls like date pickers. It doesn't second guess its input in any way.

This was all implemented when back when ISO 8601 was eliminated and the RFC 3999
only parser was introduced. It's now exposed to the `tz` caller. Well, it was
already exposed to the `tz` caller, except that it totally didn't work.

Progress on #7. Need to consider application of timezone.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          12029/11.75  5506/05.38  3458/03.38  2411/02.35
    date.js                   4591/04.48  3077/03.00  1256/01.23  1034/01.01
Smaller zone offset format function.

The `splitOffset` function was used only by the format function for the `%z`
format specifier, so its logic was placed into the format function. The logic to
split the offset into hours, minutes an seconds was rolled into a loop.

The formatting logic itself uses the length of the `delimiters` string, the
colons between the `%` and `z` to determine where to slice the array. The double
regular expressions are used to strip the zone offset in the case of the
just-make-it-long-enough option.

Not sure if I need `UTC` anymore, so I got rid if it.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          11200/10.94  5114/04.99  3288/03.21  2283/02.23
    date.js                   4591/04.48  3077/03.00  1256/01.23  1034/01.01
Further tidy of `format`.

Padding is not down using a negative parameter to `slice`. No need to build
padding strings. We know that we'll only ever need eight spaces, or eight zeros.
The `splice` method minzips better than the padding functions.

Got rid of the lookup objects for transforms and padding functions. Expressing
this logic using conditionals instead.

Replaced an if/else with a ternary operator in `convertToPOSIX`.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          10444/10.20  4922/04.81  3105/03.03  2208/02.16
    date.js                   4591/04.48  3077/03.00  1256/01.23  1034/01.01
All of the rest of GNU `date` for under 1k.

Inlining the logic in `isLeapYear` minifies better. Same with `dialHours`.

Removed lower case meridiem. Use `.toLowerCase()` to convert the upper case
meridiem. Updated the Polish locale for new meridiem storage structure.

Added logic to export in both the browser and Node.js.

    File                             Raw         Min         Zip     Min/Zip
    lib/timezone.js          10444/10.20  4922/04.81  3105/03.03  2208/02.16
    date.js                   4472/04.37  3058/02.99  1202/01.17  1012/00.99