PageRenderTime 49ms CodeModel.GetById 2ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/resources/assets/app/scripts/specs/parsers/iso8601.js

https://github.com/craigbeck/chronos
JavaScript | 1065 lines | 685 code | 148 blank | 232 comment | 21 complexity | 15a789e709fb59fec9640ce01cdc1fbd MD5 | raw file
   1define([
   2  'underscore',
   3  'jquery',
   4  'mocha',
   5  'chai',
   6  'parsers/iso8601',
   7  'components/date_node',
   8  'json!specs/test_data.json'
   9],
  10function(_,
  11         $,
  12         _mocha,
  13         Chai,
  14         Iso8601Parser,
  15         DateNode,
  16         TestData) {
  17
  18  var expect = Chai.expect,
  19      Assertion = Chai.Assertion,
  20      parse  = Iso8601Parser.parse,
  21      slice  = Array.prototype.slice,
  22      Generators;
  23
  24  function join() {
  25    return slice.call(arguments).join('');
  26  }
  27
  28  function WriteTestData(name, values) {
  29    var $el = $('#test-data'),
  30        content = {};
  31
  32    content[name] = values;
  33
  34    if ($el.val().length > 0) {
  35      _.merge(content, JSON.parse($el.val()));
  36    }
  37
  38    $el.val(JSON.stringify(content));
  39  }
  40
  41  Chai.use(function(chai, Utils) {
  42    function IsNode(v) {
  43      return (v instanceof DateNode.__super__.constructor);
  44    }
  45
  46    function IsParserResult(v) {
  47      return !!_.result(v, 'original') && !!_.result(v, 'parsed');
  48    }
  49
  50    Assertion.addMethod('parseableAs', function (parseRule) {
  51      var obj = this._obj,
  52          error,
  53          parseResult;
  54
  55      new Assertion(this._obj).to.be.a('string');
  56
  57      try {
  58        parseResult = parse(obj, parseRule);
  59      } catch (e) {
  60        error = _.pick(e,
  61          'name', 'expected', 'found', 'message', 'offset', 'line', 'column');
  62      }
  63
  64      this.assert(
  65        !error,
  66        "expected #{this} to be parseable as #{exp} but got #{act}",
  67        "expected #{this} to not be parseable, but got #{act}",
  68        parseRule,
  69        !!error ? JSON.stringify(error) : parseResult
  70      );
  71
  72      this._obj = {
  73        original: obj, parsed: parseResult
  74      };
  75
  76      return this;
  77    });
  78
  79    Assertion.overwriteMethod('respondTo', function(_super) {
  80      return function(methodName, arg) {
  81        var obj = Utils.flag(this, 'object');
  82
  83        if (IsNode(obj)) {
  84          var _method = obj[methodName],
  85              fnAssertion, wAssertion;
  86
  87          new chai.Assertion(_method).to.be.a('function');
  88
  89          if (_.isObject(arg) && _.has(arg, 'with')) {
  90            new chai.Assertion(_method.call(obj)).to.be.eql(arg['with']);
  91          }
  92        } else if (IsParserResult(obj)) {
  93          var ass = new chai.Assertion(obj.parsed);
  94          ass.to.respondTo.apply(ass, arguments);
  95        } else {
  96          _super.apply(this, arguments);
  97        }
  98      };
  99    });
 100  });
 101
 102  function T(msg, obj) {
 103    return ([
 104      msg, '- testing', _.size(obj), 'objects'
 105    ]).join(' ');
 106  }
 107
 108  function PaddedNumRange(start, end, width, prefix) {
 109    width || (width = (end + '').length);
 110    prefix || (prefix = '');
 111
 112    var steps = _.chain(1).range(width).map(function(padding) {
 113      var zeros = (new Array(padding + 1)).join('0');
 114      return {
 115        i: parseInt(1 + zeros, 10),
 116        z: zeros
 117      };
 118    }).sortBy(function(v) { return v.i; }).value();
 119
 120    function format(val) {
 121      var result, zeros;
 122      result = _.chain(steps).filter(function(v) {
 123        return v.i > val;
 124      }).max(function(v) {
 125        return v.i;
 126      }).value();
 127
 128      result = (Math.abs(result) === Infinity) ? null : result;
 129      if (!!result) {
 130        var len = result.i.toString().length - val.toString().length;
 131
 132        return [
 133          prefix,
 134          _.first(result.z, len).join(''),
 135          val
 136        ].join('');
 137      } else {
 138        return [prefix, val].join('');
 139      }
 140
 141        //find(steps, function(v) {
 142        //return (v.i > val) && ([v.z, val].join('').length <= width);
 143      //});
 144
 145      return prefix + (!!result ? (result.z + val) : ('' + val));
 146    }
 147
 148    return _.chain(start).range(end + 1).map(function(i) {
 149      return {
 150        str: format(i), int: i
 151      };
 152    }).value();
 153  }
 154
 155  function MakeDates(lists, separator) {
 156    separator || (separator = '');
 157
 158    function WithRest(a) {
 159      if (a.length === 1) { return a[0]; }
 160      else if (a.length > 1) {
 161        var rest = WithRest(a.slice(1));
 162        return rest.reduce(function(memo, item) {
 163          return memo.concat(_.first(a).map(function(w) {
 164            return {str: [w.str, item.str].join(separator)};
 165          }));
 166        }, []);
 167      }
 168    }
 169
 170    return WithRest(lists);
 171  }
 172
 173  Generators = (function () {
 174    var methods = {};
 175
 176    methods.calendarYears = _.memoize(function() {
 177      var Y1 = {str: '1984', int: 1984},
 178          Y2 = {str: '0010', int: 10},
 179          Y3 = {str: '+00501', int: 501},
 180          Y4 = {str: '-00501', int: -501},
 181          Y5 = {str: '-10000', int: -10000};
 182      return {
 183        standard: [Y1, Y2],
 184        extended: [Y3, Y4, Y5],
 185        all: [Y1, Y2, Y3, Y4, Y5]
 186      };
 187    });
 188
 189    methods.calendarMonths = _.memoize(function() {
 190      var months = PaddedNumRange(1, 12, 2);
 191
 192      return {
 193        standard: months, extended: [], all: months
 194      };
 195    });
 196
 197    methods.calendarDaysOfMonth = _.memoize(function() {
 198      var days = PaddedNumRange(1, 31);
 199
 200      return {
 201        standard: days, extended: [], all: days
 202      };
 203    });
 204
 205    methods.calendarWeeks = _.memoize(function() {
 206      var weeks = PaddedNumRange(1, 53, 2, 'W');
 207
 208      return {
 209        standard: weeks, extended: [], all: weeks
 210      };
 211    });
 212
 213    function makeResult(std, extended, all) {
 214      extended || (extended = []);
 215      all || (all = std);
 216      return {standard: std, extended: extended, all: all};
 217    }
 218
 219    methods.calendarDaysOfWeek = _.memoize(function() {
 220      var days = PaddedNumRange(1, 7);
 221      return makeResult(days, [], days);
 222    });
 223
 224    methods.calendarDaysOfYear = _.memoize(function() {
 225      var days = PaddedNumRange(1, 365, 3);
 226      return makeResult(days, [], days);
 227    });
 228
 229    methods.time || (methods.time = {});
 230    methods.time.hours = _.memoize(function() {
 231      var hours = PaddedNumRange(0, 24);
 232      return makeResult(hours, [], hours);
 233    });
 234
 235    methods.time.minutes = _.memoize(function() {
 236      var minutes = PaddedNumRange(0, 59);
 237      return makeResult(minutes, [], minutes);
 238    });
 239
 240    methods.time.seconds = _.memoize(function() {
 241      var s = PaddedNumRange(0, 60);
 242      return makeResult(s, [], s);
 243    });
 244
 245    methods.time.zones = _.memoize(function() {
 246      var tz = ['Z'];
 247      (['+', '-']).forEach(function(sign) {
 248        _.range(0, 10).forEach(function(i) {
 249        });
 250      });
 251    });
 252
 253    return methods;
 254  }());
 255
 256  describe('ISO-8601 parts', function() {
 257    var calendarYears, calendarMonths, calendarDaysOfMonth,
 258        calendarDaysOfWeek, calendarWeeks, calendarDaysOfYear;
 259
 260    var timeHours, timeMinutes, timeSeconds, timeZones;
 261
 262    before(function() {
 263      /**
 264      calendarYears = Generators.calendarYears();
 265      calendarMonths = Generators.calendarMonths();
 266      calendarDaysOfMonth = Generators.calendarDaysOfMonth();
 267      calendarDaysOfWeek = Generators.calendarDaysOfWeek();
 268      calendarWeeks = Generators.calendarWeeks();
 269      calendarDaysOfYear = Generators.calendarDaysOfYear();
 270      var obj = {
 271        parts: {
 272          years: calendarYears,
 273          months: calendarMonths,
 274          daysOfMonth: calendarDaysOfMonth,
 275          weeks: calendarWeeks,
 276          daysOfYear: calendarDaysOfYear
 277        }
 278      };
 279      WriteTestData('dates', obj);
 280      **/
 281      calendarYears = TestData.dates.parts.years;
 282      calendarMonths = TestData.dates.parts.months;
 283      calendarDaysOfMonth = TestData.dates.parts.daysOfMonth;
 284      calendarWeeks = TestData.dates.parts.weeks;
 285      calendarDaysOfYear = TestData.dates.parts.daysOfYear;
 286    });
 287
 288    describe('Dates', function() {
 289
 290      describe('Years part', function() {
 291        it('should properly parse standard YYYY', function() {
 292          var parseResult;
 293
 294          calendarYears.standard.forEach(function(y, i) {
 295            expect(y.str).to.be.parseableAs('YYYY').
 296              and.to.respondTo('getValue', {'with': y.int});
 297          }, this);
 298        });
 299
 300        it('should properly parse extended [+-]Y?YYYY', function() {
 301          var parseResult;
 302
 303          calendarYears.extended.forEach(function(y, i) {
 304            expect(y.str).to.be.parseableAs('YYYY').
 305              and.to.respondTo('getValue', {'with': y.int});
 306          }, this);
 307        });
 308      });
 309
 310      describe('Month of year part', function() {
 311        it('should properly parse MM', function() {
 312          var parseResult;
 313
 314          calendarMonths.all.forEach(function(m, i) {
 315            var parseResult = expect(m.str).to.be.parseableAs('MM');
 316          });
 317        });
 318      });
 319
 320      describe('Day of month part', function() {
 321        it('should properly parse DD', function() {
 322          var parseResult;
 323
 324          calendarDaysOfMonth.all.forEach(function(d, i) {
 325            var parseResult = expect(d.str).to.be.parseableAs('DD');
 326          });
 327        });
 328      });
 329
 330      describe('Calendar Dates', function() {
 331        var cDateFullDash, cDateFull, cDateDash, cDate;
 332
 333        before(function() {
 334          /**
 335          cDateFullDash = MakeDates([
 336            calendarYears.all,
 337            calendarMonths.all,
 338            calendarDaysOfMonth.all
 339          ], '-');
 340
 341          cDateFull = MakeDates([
 342            calendarYears.all,
 343            calendarMonths.all,
 344            calendarDaysOfMonth.all
 345          ]);
 346
 347          cDateDash = MakeDates([
 348            calendarYears.all,
 349            calendarMonths.all
 350          ], '-');
 351
 352          cDate = MakeDates([
 353            calendarYears.all,
 354            calendarMonths.all
 355          ]);
 356
 357          var obj = {
 358            calendar: {
 359              dateFullDash: cDateFullDash,
 360              dateFull: cDateFull,
 361              dateDash: cDateDash,
 362              date: cDate
 363            }
 364          };
 365
 366          WriteTestData('dates', obj);
 367         **/
 368          cDateFullDash = TestData.dates.calendar.dateFullDash;
 369          cDateFull = TestData.dates.calendar.dateFull;
 370          cDateDash = TestData.dates.calendar.dateDash;
 371          cDate = TestData.dates.calendar.date;
 372        });
 373
 374        describe('with dashes', function() {
 375          it('should parse full dates', function() {
 376
 377            cDateFullDash.forEach(function(date) {
 378              expect(date.str).to.be.parseableAs('Date');
 379            }, this);
 380          });
 381
 382          it('should parse dates without [DD]', function() {
 383            cDateFull.forEach(function(date) {
 384              expect(date.str).to.be.parseableAs('Date');
 385            }, this);
 386          });
 387        });
 388
 389        describe('without dashes', function() {
 390          it('should parse full dates', function() {
 391            cDateFull.forEach(function(date) {
 392              expect(date.str).to.be.parseableAs('Date');
 393            }, this);
 394          });
 395
 396          it('should NOT parse dates without [DD]', function() {
 397            cDate.forEach(function(date) {
 398              expect(date.str).not.to.be.parseableAs('Date');
 399            }, this);
 400          });
 401        });
 402      });
 403
 404      describe('Week Dates', function() {
 405        var wDateFullDash, wDateFull, wDateDash, wDate;
 406
 407        before(function() {
 408          /**
 409          wDateFullDash = MakeDates([
 410            calendarYears.all,
 411            calendarWeeks.all,
 412            calendarDaysOfWeek.all
 413          ], '-');
 414          wDateFull = MakeDates([
 415            calendarYears.all,
 416            calendarWeeks.all,
 417            calendarDaysOfWeek.all
 418          ]);
 419          wDateDash = MakeDates([
 420            calendarYears.all,
 421            calendarWeeks.all
 422          ], '-');
 423          wDate = MakeDates([
 424            calendarYears.all,
 425            calendarWeeks.all
 426          ]);
 427
 428          var obj = {
 429            week: {
 430              dateFullDash: wDateFullDash,
 431              dateFull: wDateFull,
 432              dateDash: wDateDash,
 433              date: wDate
 434            }
 435          };
 436
 437          WriteTestData('dates', obj);
 438          **/
 439          wDateFullDash = TestData.dates.week.dateFullDash;
 440          wDateFull = TestData.dates.week.dateFull;
 441          wDateDash = TestData.dates.week.dateDash;
 442          wDate = TestData.dates.week.date;
 443        });
 444
 445        describe('with dashes', function() {
 446          it('should parse full dates', function() {
 447
 448            wDateFullDash.forEach(function(date) {
 449              expect(date.str).to.be.parseableAs('Date');
 450            }, this);
 451          });
 452
 453          it('should parse dates without [D]', function() {
 454            wDateFull.forEach(function(date) {
 455              expect(date.str).to.be.parseableAs('Date');
 456            }, this);
 457          });
 458        });
 459
 460        describe('without dashes', function() {
 461          it('should parse full dates', function() {
 462            wDateFull.forEach(function(date) {
 463              expect(date.str).to.be.parseableAs('Date');
 464            }, this);
 465          });
 466
 467          it('should parse dates without [D]', function() {
 468            wDate.forEach(function(date) {
 469              expect(date.str).to.be.parseableAs('Date');
 470            }, this);
 471          });
 472        });
 473      });
 474
 475      describe('Ordinal Dates', function() {
 476        var oDateDash, oDate;
 477
 478        before(function() {
 479          /**
 480          oDateDash = MakeDates([
 481            calendarYears.all,
 482            calendarDaysOfYear.all
 483          ], '-');
 484          oDate = MakeDates([
 485            calendarYears.all,
 486            calendarDaysOfYear.all
 487          ]);
 488
 489          var obj = {
 490            ordinal: {
 491              dateDash: oDateDash,
 492              date: oDate
 493            }
 494          };
 495
 496          WriteTestData('dates', obj);
 497          **/
 498          oDateDash = TestData.dates.ordinal.dateDash;
 499          oDate = TestData.dates.ordinal.date;
 500        });
 501
 502        describe('with dashes', function() {
 503          it('should parse full dates', function() {
 504
 505            oDateDash.forEach(function(date) {
 506              expect(date.str).to.be.parseableAs('Date');
 507            }, this);
 508          });
 509        });
 510
 511        describe('without dashes', function() {
 512          it('should parse full dates', function() {
 513            oDate.forEach(function(date) {
 514              expect(date.str).to.be.parseableAs('Date');
 515            }, this);
 516          });
 517        });
 518      });
 519    });
 520
 521    before(function() {
 522      timeHours = Generators.time.hours();
 523      timeMinutes = Generators.time.minutes();
 524      timeSeconds = Generators.time.seconds();
 525      timeZones = Generators.time.zones();
 526    });
 527
 528    describe('Times', function() {
 529      var hh_mm_ss, hh_mm, hhmmss, hhmm, hh,
 530          hh_mm_ss_tz, hh_mm_tz, hhmmss_tz, hhmm_tz, hh_tz;
 531
 532      before(function() {
 533        /**
 534        hh_mm_ss = MakeDates([
 535          timeHours.all,
 536          timeMinutes.all,
 537          timeSeconds.all
 538        ], ':');
 539        hh_mm = MakeDates([
 540          timeHours.all,
 541          timeMinutes.all
 542        ], ':');
 543        hhmmss = MakeDates([
 544          timeHours.all,
 545          timeMinutes.all,
 546          timeSeconds.all
 547        ]);
 548        hhmm = MakeDates([
 549          timeHours.all,
 550          timeMinutes.all
 551        ]);
 552        hh = MakeDates([
 553          timeHours.all
 554        ]);
 555
 556        var obj = {
 557          week: {
 558            hh_mm_ss: hh_mm_ss,
 559            hh_mm: hh_mm,
 560            hhmmss: hhmmss,
 561            hhmm: hhmm,
 562            hh: hh
 563          }
 564        };
 565
 566        WriteTestData('times', obj);
 567        **/
 568
 569        hh_mm_ss = TestData.times.week.hh_mm_ss;
 570        hh_mm = TestData.times.week.hh_mm;
 571        hhmmss = TestData.times.week.hhmmss;
 572        hhmm = TestData.times.week.hhmm;
 573        hh = TestData.times.week.hh;
 574      });
 575
 576      describe('without timezones', function() {
 577
 578        describe('with colons', function() {
 579          it(T('should parse hh:mm:ss', hh_mm_ss), function() {
 580
 581            hh_mm_ss.forEach(function(time) {
 582              expect(time.str).to.be.parseableAs('Time');
 583            }, this);
 584          });
 585
 586          it(T('should parse hh:mm', hh_mm), function() {
 587            hh_mm.forEach(function(time) {
 588              expect(time.str).to.be.parseableAs('Time');
 589            }, this);
 590          });
 591        });
 592
 593        describe('without colons', function() {
 594          it(T('should parse hhmmss', hhmmss), function() {
 595            hhmmss.forEach(function(time) {
 596              expect(time.str).to.be.parseableAs('Time');
 597            }, this);
 598          });
 599
 600          it(T('should parse hhmm', hhmm), function() {
 601            hhmm.forEach(function(time) {
 602              expect(time.str).to.be.parseableAs('Time');
 603            }, this);
 604          });
 605
 606          it(T('should parse hh', hh), function() {
 607            hh.forEach(function(time) {
 608              expect(time.str).to.be.parseableAs('Time');
 609            }, this);
 610          });
 611        });
 612      });
 613
 614      var datesWithTimezones;
 615
 616      before(function() {
 617        /**
 618        var timezones = ['Z'];
 619        var tzFormats = {'-': [], '+': []};
 620
 621        (['+', '-']).forEach(function(sign) {
 622          ([hh_mm, hhmm, hh]).forEach(function(list, j) {
 623            tzFormats[sign][j] = [];
 624
 625            list.forEach(function(item, k) {
 626              tzFormats[sign][j].push(_.extend({}, item, {
 627                str: [sign, item.str].join('')
 628              }));
 629            });
 630          });
 631        });
 632
 633        timezones = timezones.concat.apply(timezones,
 634          _.chain(tzFormats).values().flatten());
 635
 636        function mergeTimezone(timeVal, tz) {
 637          return _.extend({}, timeVal, {
 638            str: [timeVal.str, tz.str].join(''),
 639            tz: tz.str
 640          });
 641        }
 642
 643        function makeTzTime(times, tzs) {
 644          return times.reduce(function(memo, item) {
 645            tzs.forEach(function(tz) {
 646              memo.push(mergeTimezone(item, tz));
 647            });
 648            return memo;
 649          }, []);
 650        }
 651
 652        hh_mm_ss_tz = makeTzTime(hh_mm_ss, timezones);
 653        hh_mm_tz = makeTzTime(hh_mm, timezones);
 654        hhmmss_tz = makeTzTime(hhmmss, timezones);
 655        hhmm_tz = makeTzTime(hhmm, timezones);
 656        hh_tz = makeTzTime(hh, timezones);
 657
 658        var obj = {
 659          week: {
 660            hh_mm_ss_tz: hh_mm_ss_tz,
 661            hh_mm_tz: hh_mm_tz,
 662            hhmmss_tz: hhmmss_tz,
 663            hhmm_tz: hhmm_tz,
 664            hh_tz: hh_tz
 665          }
 666        };
 667        WriteTestData('time_zones', obj);
 668        **/
 669
 670        hh_mm_ss_tz = TestData.time_zones.week.hh_mm_ss_tz;
 671        hh_mm_tz = TestData.time_zones.week.hh_mm_tz;
 672        hhmmss_tz = TestData.time_zones.week.hhmmss_tz;
 673        hhmm_tz = TestData.time_zones.week.hhmm_tz;
 674        hh_tz = TestData.time_zones.week.hh_tz;
 675      });
 676
 677      describe('with timezones', function() {
 678
 679        describe('just timzones', function() {
 680          it('should parse Z', function() {
 681            expect('Z').to.be.parseableAs('TimeZone');
 682          });
 683
 684          it(T('should parse +hh:mm', hh_mm), function() {
 685            hh_mm.forEach(function(time) {
 686              expect(join('+', time.str)).to.be.parseableAs('TimeZone');
 687            }, this);
 688          });
 689
 690          it(T('should parse -hh:mm', hh_mm), function() {
 691            hh_mm.forEach(function(time) {
 692              expect(join('-', time.str)).to.be.parseableAs('TimeZone');
 693            }, this);
 694          });
 695
 696          it(T('should parse +hhmm', hh_mm), function() {
 697            hhmm.forEach(function(time) {
 698              expect(join('+', time.str)).to.be.parseableAs('TimeZone');
 699            }, this);
 700          });
 701
 702          it(T('should parse -hhmm', hh_mm), function() {
 703            hhmm.forEach(function(time) {
 704              expect(join('-', time.str)).to.be.parseableAs('TimeZone');
 705            }, this);
 706          });
 707
 708          it(T('should parse +hh', hh), function() {
 709            hh.forEach(function(time) {
 710              expect(join('+', time.str)).to.be.parseableAs('TimeZone');
 711            });
 712          });
 713
 714          it(T('should parse -hh', hh), function() {
 715            hh.forEach(function(time) {
 716              expect(join('-', time.str)).to.be.parseableAs('TimeZone');
 717            });
 718          });
 719        });
 720
 721        describe('combined timezones and times', function() {
 722
 723          describe('with colons', function() {
 724            it(T('should parse hh:mm:ss + tz', hh_mm_ss_tz), function() {
 725
 726              hh_mm_ss_tz.forEach(function(time) {
 727                expect(time.str).to.be.parseableAs('Time');
 728              }, this);
 729            });
 730
 731            it(T('should parse hh:mm + tz', hh_mm_tz), function() {
 732              hh_mm_tz.forEach(function(time) {
 733                expect(time.str).to.be.parseableAs('Time');
 734              }, this);
 735            });
 736          });
 737
 738          describe('without colons', function() {
 739            it(T('should parse hhmmss + tz', hhmmss_tz), function() {
 740              hhmmss_tz.forEach(function(time) {
 741                expect(time.str).to.be.parseableAs('Time');
 742              }, this);
 743            });
 744
 745            it(T('should parse hhmm + tz', hhmm_tz), function() {
 746              hhmm_tz.forEach(function(time) {
 747                expect(time.str).to.be.parseableAs('Time');
 748              }, this);
 749            });
 750
 751            it(T('should parse hh + tz', hh_tz), function() {
 752              hh_tz.forEach(function(time) {
 753                expect(time.str).to.be.parseableAs('Time');
 754              }, this);
 755            });
 756          });
 757        });
 758      });
 759    });
 760
 761    describe('Date Times', function() {
 762      var oDates, calendarDates, weekDates, times, tzTimes;
 763
 764      before(function() {
 765        //dashed: TestData.dates.ordinal.dateDash,
 766        //normal: TestData.dates.ordinal.date
 767        oDates = TestData.dates.ordinal;
 768
 769        //cDateFullDash = TestData.dates.calendar.dateFullDash;
 770        //cDateFull = TestData.dates.calendar.dateFull;
 771        //cDateDash = TestData.dates.calendar.dateDash;
 772        //cDate = TestData.dates.calendar.date;
 773        calendarDates = TestData.dates.calendar;
 774
 775        //wDateFullDash = TestData.dates.week.dateFullDash;
 776        //wDateFull = TestData.dates.week.dateFull;
 777        //wDateDash = TestData.dates.week.dateDash;
 778        //wDate = TestData.dates.week.date;
 779        weekDates = TestData.dates.week;
 780
 781        //hh_mm_ss = TestData.times.week.hh_mm_ss;
 782        //hh_mm = TestData.times.week.hh_mm;
 783        //hhmmss = TestData.times.week.hhmmss;
 784        //hhmm = TestData.times.week.hhmm;
 785        //hh = TestData.times.week.hh;
 786        times = TestData.times.week;
 787
 788        //hh_mm_ss_tz = TestData.time_zones.week.hh_mm_ss_tz;
 789        //hh_mm_tz = TestData.time_zones.week.hh_mm_tz;
 790        //hhmmss_tz = TestData.time_zones.week.hhmmss_tz;
 791        //hhmm_tz = TestData.time_zones.week.hhmm_tz;
 792        //hh_tz = TestData.time_zones.week.hh_tz;
 793        tzTimes = TestData.time_zones.week;
 794      });
 795
 796      describe('with ordinal dates', function() {
 797        var dates = oDates;
 798
 799        describe('with timezones', function() {
 800          it('should parse', function() {
 801            _.each(dates, function(dateList, k) {
 802              dateList.forEach(function(date) {
 803                _.each(tzTimes, function(tzList, tzKey) {
 804                  tzList.forEach(function(tzTime) {
 805                    expect(join(date, 'T', tzTime)).to.be.parseableAs('DateTime');
 806                  }, this);
 807                }, this);
 808              }, this);
 809            }, this);
 810          });
 811        });
 812
 813        describe('without timezones', function() {
 814          it('should parse', function() {
 815            _.each(dates, function(dateList, k) {
 816              dateList.forEach(function(date) {
 817                _.each(times, function(tzList, tzKey) {
 818                  tzList.forEach(function(tzTime) {
 819                    expect(join(date, 'T', tzTime)).to.be.parseableAs('DateTime');
 820                  }, this);
 821                }, this);
 822              }, this);
 823            }, this);
 824          });
 825        });
 826      });
 827
 828      describe('with calendar dates', function() {
 829        var dates = calendarDates;
 830
 831        describe('with timezones', function() {
 832          it('should parse', function() {
 833            _.each(dates, function(dateList, k) {
 834              dateList.forEach(function(date) {
 835                _.each(tzTimes, function(tzList, tzKey) {
 836                  tzList.forEach(function(tzTime) {
 837                    expect(join(date, 'T', tzTime)).to.be.parseableAs('DateTime');
 838                  }, this);
 839                }, this);
 840              }, this);
 841            }, this);
 842          });
 843        });
 844
 845        describe('without timezones', function() {
 846          it('should parse', function() {
 847            _.each(dates, function(dateList, k) {
 848              dateList.forEach(function(date) {
 849                _.each(times, function(tzList, tzKey) {
 850                  tzList.forEach(function(tzTime) {
 851                    expect(join(date, 'T', tzTime)).to.be.parseableAs('DateTime');
 852                  }, this);
 853                }, this);
 854              }, this);
 855            }, this);
 856          });
 857        });
 858      });
 859
 860      describe('with week dates', function() {
 861        var dates = weekDates;
 862
 863        describe('with timezones', function() {
 864          it('should parse', function() {
 865            _.each(dates, function(dateList, k) {
 866              dateList.forEach(function(date) {
 867                _.each(tzTimes, function(tzList, tzKey) {
 868                  tzList.forEach(function(tzTime) {
 869                    expect(join(date, 'T', tzTime)).to.be.parseableAs('DateTime');
 870                  }, this);
 871                }, this);
 872              }, this);
 873            }, this);
 874          });
 875        });
 876
 877        describe('without timezones', function() {
 878          it('should parse', function() {
 879            _.each(dates, function(dateList, k) {
 880              dateList.forEach(function(date) {
 881                _.each(times, function(tzList, tzKey) {
 882                  tzList.forEach(function(tzTime) {
 883                    expect(join(date, 'T', tzTime)).to.be.parseableAs('DateTime');
 884                  }, this);
 885                }, this);
 886              }, this);
 887            }, this);
 888          });
 889        });
 890      });
 891
 892    });
 893
 894    describe('Durations', function() {
 895      var oDates, calendarDates, weekDates, times, tzTimes;
 896
 897      before(function() {
 898        //dashed: TestData.dates.ordinal.dateDash,
 899        //normal: TestData.dates.ordinal.date
 900        oDates = TestData.dates.ordinal;
 901
 902        //cDateFullDash = TestData.dates.calendar.dateFullDash;
 903        //cDateFull = TestData.dates.calendar.dateFull;
 904        //cDateDash = TestData.dates.calendar.dateDash;
 905        //cDate = TestData.dates.calendar.date;
 906        calendarDates = TestData.dates.calendar;
 907
 908        //wDateFullDash = TestData.dates.week.dateFullDash;
 909        //wDateFull = TestData.dates.week.dateFull;
 910        //wDateDash = TestData.dates.week.dateDash;
 911        //wDate = TestData.dates.week.date;
 912        weekDates = TestData.dates.week;
 913
 914        //hh_mm_ss = TestData.times.week.hh_mm_ss;
 915        //hh_mm = TestData.times.week.hh_mm;
 916        //hhmmss = TestData.times.week.hhmmss;
 917        //hhmm = TestData.times.week.hhmm;
 918        //hh = TestData.times.week.hh;
 919        times = TestData.times.week;
 920
 921        //hh_mm_ss_tz = TestData.time_zones.week.hh_mm_ss_tz;
 922        //hh_mm_tz = TestData.time_zones.week.hh_mm_tz;
 923        //hhmmss_tz = TestData.time_zones.week.hhmmss_tz;
 924        //hhmm_tz = TestData.time_zones.week.hhmm_tz;
 925        //hh_tz = TestData.time_zones.week.hh_tz;
 926        tzTimes = TestData.time_zones.week;
 927      });
 928
 929      describe('as PnYnMnDTnHnMnS', function() {
 930        var firstHalves, secondHalves, together;
 931
 932        before(function() {
 933          var n = 10;
 934
 935          var fHalves, sHalves;
 936
 937          fHalves = _.chain(n).range().map(function(i) {
 938            return (['Y', 'M', 'D']).reduce(function(memo, sig) {
 939              var v = _.random(0, n - 1);
 940              if (v > 0) { memo.push(join(v, sig)) }
 941              return memo;
 942            }, []);
 943          });
 944
 945          sHalves = _.chain(n).range().map(function(i) {
 946            return join.apply(null, (['H', 'M', 'S']).reduce(function(memo, sig) {
 947              var v = _.random(0, i);
 948              if (v > 0) { memo.push(join(v, sig)) }
 949              return memo;
 950            }, []));
 951          });
 952
 953          firstHalves = fHalves.map(function(h) {
 954            return join.apply(null, (['P']).concat(h));
 955          });
 956          secondHalves = sHalves.map(function(h) {
 957            return join.apply(null, (['P', 'T']).concat(h));
 958          });
 959
 960          together = fHalves.reduce(function(memo, fh) {
 961            sHalves.forEach(function(sh) {
 962              memo.push(join.apply(null, (['P']).concat(fh).concat('T', sh)));
 963            });
 964            return memo;
 965          }, []);
 966        });
 967
 968        describe('full specifier', function() {
 969          it('should parse', function() {
 970            together.forEach(function(d) {
 971              expect(d).to.be.parseableAs('Duration');
 972            });
 973          });
 974
 975          it('should parse just first half', function() {
 976            firstHalves.forEach(function(d) {
 977              expect(d).to.be.parseableAs('Duration');
 978            });
 979          });
 980
 981          it('should parse just second half', function() {
 982            secondHalves.forEach(function(d) {
 983              expect(d).to.be.parseableAs('Duration');
 984            });
 985          });
 986        });
 987      });
 988
 989      describe('as PnW', function() {
 990        _.range(1, 53).forEach(function(i) {
 991          expect(join('P', i, 'W')).to.be.parseableAs('Duration');
 992        }, this);
 993      });
 994
 995      describe('as P<date>T<time>', function() {
 996        var n = 20;
 997
 998        describe('with week dates', function() {
 999          it('should parse', function() {
1000            _.chain(weekDates).first(n).forEach(function(date) {
1001              _.each(tzTimes, function(tzList, tzKey) {
1002                tzList.forEach(function(tzTime) {
1003                  expect(join('P', date.str, 'T', tzTime.str)).to.be.parseableAs('Duration');
1004                }, this);
1005              }, this);
1006            }, this);
1007          });
1008        });
1009
1010        describe('with ordinal dates', function() {
1011          it('should parse', function() {
1012            _.chain(oDates).first(n).forEach(function(date) {
1013              _.each(tzTimes, function(tzList, tzKey) {
1014                tzList.forEach(function(tzTime) {
1015                  expect(join('P', date.str, 'T', tzTime.str)).to.be.parseableAs('Duration');
1016                }, this);
1017              }, this);
1018            }, this);
1019          });
1020        });
1021
1022        describe('with calendar dates', function() {
1023          it('should parse', function() {
1024            _.chain(calendarDates).first(n).forEach(function(date) {
1025              _.each(tzTimes, function(tzList, tzKey) {
1026                tzList.forEach(function(tzTime) {
1027                  expect(join('P', date.str, 'T', tzTime.str)).to.be.parseableAs('Duration');
1028                }, this);
1029              }, this);
1030            }, this);
1031          });
1032        });
1033      });
1034    });
1035
1036    describe('Time intervals', function() {
1037      var formats = {
1038        '<start>/<end>': '2007-03-01T13:00:00Z/2008-05-11T15:30:00Z',
1039        '<start>/<duration>': '2007-03-01T13:00:00Z/P1Y2M10DT2H30M',
1040        '<duration>/<end>': 'P1Y2M10DT2H30M/2008-05-11T15:30:00Z'
1041      };
1042
1043      _.each(formats, function(v, k) {
1044        it(join('should parse', k), function() {
1045          expect(v).to.be.parseableAs('Interval');
1046        });
1047      }, this);
1048    });
1049
1050    describe('Repeating intervals', function() {
1051      var formats = {
1052        'Rnn/<interval>': 'R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M',
1053        'R/<interval>': 'R/P1Y2M10DT2H30M/2008-05-11T15:30:00Z'
1054      };
1055
1056      _.each(formats, function(v, k) {
1057        it(join('should parse', k), function() {
1058          expect(v).to.be.parseableAs('RepeatingInterval');
1059        });
1060      }, this);
1061    });
1062
1063    return true;
1064  });
1065});