@@ -373,146 +373,176 @@ angular.mock.$LogProvider = function() {
373373} ;
374374
375375
376- /**
377- * @ngdoc object
378- * @name angular.mock.TzDate
379- * @description
380- *
381- * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
382- *
383- * Mock of the Date type which has its timezone specified via constroctor arg.
384- *
385- * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
386- * offset, so that we can test code that depends on local timezone settings without dependency on
387- * the time zone settings of the machine where the code is running.
388- *
389- * @param {number } offset Offset of the *desired* timezone in hours (fractions will be honored)
390- * @param {(number|string) } timestamp Timestamp representing the desired time in *UTC*
391- *
392- * @example
393- * !!!! WARNING !!!!!
394- * This is not a complete Date object so only methods that were implemented can be called safely.
395- * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
396- *
397- * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
398- * incomplete we might be missing some non-standard methods. This can result in errors like:
399- * "Date.prototype.foo called on incompatible Object".
400- *
401- * <pre>
402- * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
403- * newYearInBratislava.getTimezoneOffset() => -60;
404- * newYearInBratislava.getFullYear() => 2010;
405- * newYearInBratislava.getMonth() => 0;
406- * newYearInBratislava.getDate() => 1;
407- * newYearInBratislava.getHours() => 0;
408- * newYearInBratislava.getMinutes() => 0;
409- * </pre>
410- *
411- */
412- angular . mock . TzDate = function ( offset , timestamp ) {
413- var self = new Date ( 0 ) ;
414- if ( angular . isString ( timestamp ) ) {
415- var tsStr = timestamp ;
416-
417- self . origDate = angular . fromJson ( angular . toJson ( { date :timestamp } ) ) . date ;
418-
419- timestamp = self . origDate . getTime ( ) ;
420- if ( isNaN ( timestamp ) )
421- throw {
422- name : "Illegal Argument" ,
423- message : "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
424- } ;
425- } else {
426- self . origDate = new Date ( timestamp ) ;
376+ ( function ( ) {
377+ var R_ISO8061_STR = / ^ ( \d { 4 } ) - ? ( \d \d ) - ? ( \d \d ) (?: T ( \d \d ) (?: \: ? ( \d \d ) (?: \: ? ( \d \d ) (?: \. ( \d { 3 } ) ) ? ) ? ) ? ( Z | ( [ + - ] ) ( \d \d ) : ? ( \d \d ) ) ) ? $ / ;
378+
379+ function jsonStringToDate ( string ) {
380+ var match ;
381+ if ( match = string . match ( R_ISO8061_STR ) ) {
382+ var date = new Date ( 0 ) ,
383+ tzHour = 0 ,
384+ tzMin = 0 ;
385+ if ( match [ 9 ] ) {
386+ tzHour = int ( match [ 9 ] + match [ 10 ] ) ;
387+ tzMin = int ( match [ 9 ] + match [ 11 ] ) ;
388+ }
389+ date . setUTCFullYear ( int ( match [ 1 ] ) , int ( match [ 2 ] ) - 1 , int ( match [ 3 ] ) ) ;
390+ date . setUTCHours ( int ( match [ 4 ] || 0 ) - tzHour , int ( match [ 5 ] || 0 ) - tzMin , int ( match [ 6 ] || 0 ) , int ( match [ 7 ] || 0 ) ) ;
391+ return date ;
392+ }
393+ return string ;
427394 }
428395
429- var localOffset = new Date ( timestamp ) . getTimezoneOffset ( ) ;
430- self . offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60 ;
431- self . date = new Date ( timestamp + self . offsetDiff ) ;
396+ function int ( str ) {
397+ return parseInt ( str , 10 ) ;
398+ }
432399
433- self . getTime = function ( ) {
434- return self . date . getTime ( ) - self . offsetDiff ;
435- } ;
436400
437- self . toLocaleDateString = function ( ) {
438- return self . date . toLocaleDateString ( ) ;
439- } ;
401+ /**
402+ * @ngdoc object
403+ * @name angular.mock.TzDate
404+ * @description
405+ *
406+ * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
407+ *
408+ * Mock of the Date type which has its timezone specified via constroctor arg.
409+ *
410+ * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
411+ * offset, so that we can test code that depends on local timezone settings without dependency on
412+ * the time zone settings of the machine where the code is running.
413+ *
414+ * @param {number } offset Offset of the *desired* timezone in hours (fractions will be honored)
415+ * @param {(number|string) } timestamp Timestamp representing the desired time in *UTC*
416+ *
417+ * @example
418+ * !!!! WARNING !!!!!
419+ * This is not a complete Date object so only methods that were implemented can be called safely.
420+ * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
421+ *
422+ * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
423+ * incomplete we might be missing some non-standard methods. This can result in errors like:
424+ * "Date.prototype.foo called on incompatible Object".
425+ *
426+ * <pre>
427+ * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
428+ * newYearInBratislava.getTimezoneOffset() => -60;
429+ * newYearInBratislava.getFullYear() => 2010;
430+ * newYearInBratislava.getMonth() => 0;
431+ * newYearInBratislava.getDate() => 1;
432+ * newYearInBratislava.getHours() => 0;
433+ * newYearInBratislava.getMinutes() => 0;
434+ * </pre>
435+ *
436+ */
437+ angular . mock . TzDate = function ( offset , timestamp ) {
438+ var self = new Date ( 0 ) ;
439+ if ( angular . isString ( timestamp ) ) {
440+ var tsStr = timestamp ;
441+
442+ self . origDate = jsonStringToDate ( timestamp )
443+
444+ timestamp = self . origDate . getTime ( ) ;
445+ if ( isNaN ( timestamp ) )
446+ throw {
447+ name : "Illegal Argument" ,
448+ message : "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
449+ } ;
450+ } else {
451+ self . origDate = new Date ( timestamp ) ;
452+ }
440453
441- self . getFullYear = function ( ) {
442- return self . date . getFullYear ( ) ;
443- } ;
454+ var localOffset = new Date ( timestamp ) . getTimezoneOffset ( ) ;
455+ self . offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60 ;
456+ self . date = new Date ( timestamp + self . offsetDiff ) ;
444457
445- self . getMonth = function ( ) {
446- return self . date . getMonth ( ) ;
447- } ;
458+ self . getTime = function ( ) {
459+ return self . date . getTime ( ) - self . offsetDiff ;
460+ } ;
448461
449- self . getDate = function ( ) {
450- return self . date . getDate ( ) ;
451- } ;
462+ self . toLocaleDateString = function ( ) {
463+ return self . date . toLocaleDateString ( ) ;
464+ } ;
452465
453- self . getHours = function ( ) {
454- return self . date . getHours ( ) ;
455- } ;
466+ self . getFullYear = function ( ) {
467+ return self . date . getFullYear ( ) ;
468+ } ;
456469
457- self . getMinutes = function ( ) {
458- return self . date . getMinutes ( ) ;
459- } ;
470+ self . getMonth = function ( ) {
471+ return self . date . getMonth ( ) ;
472+ } ;
460473
461- self . getSeconds = function ( ) {
462- return self . date . getSeconds ( ) ;
463- } ;
474+ self . getDate = function ( ) {
475+ return self . date . getDate ( ) ;
476+ } ;
464477
465- self . getTimezoneOffset = function ( ) {
466- return offset * 60 ;
467- } ;
478+ self . getHours = function ( ) {
479+ return self . date . getHours ( ) ;
480+ } ;
468481
469- self . getUTCFullYear = function ( ) {
470- return self . origDate . getUTCFullYear ( ) ;
471- } ;
482+ self . getMinutes = function ( ) {
483+ return self . date . getMinutes ( ) ;
484+ } ;
472485
473- self . getUTCMonth = function ( ) {
474- return self . origDate . getUTCMonth ( ) ;
475- } ;
486+ self . getSeconds = function ( ) {
487+ return self . date . getSeconds ( ) ;
488+ } ;
476489
477- self . getUTCDate = function ( ) {
478- return self . origDate . getUTCDate ( ) ;
479- } ;
490+ self . getTimezoneOffset = function ( ) {
491+ return offset * 60 ;
492+ } ;
480493
481- self . getUTCHours = function ( ) {
482- return self . origDate . getUTCHours ( ) ;
483- } ;
494+ self . getUTCFullYear = function ( ) {
495+ return self . origDate . getUTCFullYear ( ) ;
496+ } ;
484497
485- self . getUTCMinutes = function ( ) {
486- return self . origDate . getUTCMinutes ( ) ;
487- } ;
498+ self . getUTCMonth = function ( ) {
499+ return self . origDate . getUTCMonth ( ) ;
500+ } ;
488501
489- self . getUTCSeconds = function ( ) {
490- return self . origDate . getUTCSeconds ( ) ;
491- } ;
502+ self . getUTCDate = function ( ) {
503+ return self . origDate . getUTCDate ( ) ;
504+ } ;
492505
493- self . getDay = function ( ) {
494- return self . date . getDay ( ) ;
495- } ;
506+ self . getUTCHours = function ( ) {
507+ return self . origDate . getUTCHours ( ) ;
508+ } ;
496509
497- //hide all methods not implemented in this mock that the Date prototype exposes
498- var unimplementedMethods = [ 'getMilliseconds' , 'getUTCDay' ,
499- 'getUTCMilliseconds' , 'getYear' , 'setDate' , 'setFullYear' , 'setHours' , 'setMilliseconds' ,
500- 'setMinutes' , 'setMonth' , 'setSeconds' , 'setTime' , 'setUTCDate' , 'setUTCFullYear' ,
501- 'setUTCHours' , 'setUTCMilliseconds' , 'setUTCMinutes' , 'setUTCMonth' , 'setUTCSeconds' ,
502- 'setYear' , 'toDateString' , 'toJSON' , 'toGMTString' , 'toLocaleFormat' , 'toLocaleString' ,
503- 'toLocaleTimeString' , 'toSource' , 'toString' , 'toTimeString' , 'toUTCString' , 'valueOf' ] ;
504-
505- angular . forEach ( unimplementedMethods , function ( methodName ) {
506- self [ methodName ] = function ( ) {
507- throw Error ( "Method '" + methodName + "' is not implemented in the TzDate mock" ) ;
510+ self . getUTCMinutes = function ( ) {
511+ return self . origDate . getUTCMinutes ( ) ;
508512 } ;
509- } ) ;
510513
511- return self ;
512- } ;
514+ self . getUTCSeconds = function ( ) {
515+ return self . origDate . getUTCSeconds ( ) ;
516+ } ;
517+
518+ self . getUTCMilliseconds = function ( ) {
519+ return self . origDate . getUTCMilliseconds ( ) ;
520+ } ;
521+
522+ self . getDay = function ( ) {
523+ return self . date . getDay ( ) ;
524+ } ;
525+
526+ //hide all methods not implemented in this mock that the Date prototype exposes
527+ var unimplementedMethods = [ 'getMilliseconds' , 'getUTCDay' ,
528+ 'getYear' , 'setDate' , 'setFullYear' , 'setHours' , 'setMilliseconds' ,
529+ 'setMinutes' , 'setMonth' , 'setSeconds' , 'setTime' , 'setUTCDate' , 'setUTCFullYear' ,
530+ 'setUTCHours' , 'setUTCMilliseconds' , 'setUTCMinutes' , 'setUTCMonth' , 'setUTCSeconds' ,
531+ 'setYear' , 'toDateString' , 'toJSON' , 'toGMTString' , 'toLocaleFormat' , 'toLocaleString' ,
532+ 'toLocaleTimeString' , 'toSource' , 'toString' , 'toTimeString' , 'toUTCString' , 'valueOf' ] ;
533+
534+ angular . forEach ( unimplementedMethods , function ( methodName ) {
535+ self [ methodName ] = function ( ) {
536+ throw Error ( "Method '" + methodName + "' is not implemented in the TzDate mock" ) ;
537+ } ;
538+ } ) ;
539+
540+ return self ;
541+ } ;
513542
514- //make "tzDateInstance instanceof Date" return true
515- angular . mock . TzDate . prototype = Date . prototype ;
543+ //make "tzDateInstance instanceof Date" return true
544+ angular . mock . TzDate . prototype = Date . prototype ;
545+ } ) ( ) ;
516546
517547
518548/**
0 commit comments