Skip to content
This repository has been archived by the owner on May 21, 2019. It is now read-only.

Commit

Permalink
Merge pull request #11 from dnasir/dev
Browse files Browse the repository at this point in the history
Merge dev > master
  • Loading branch information
dnasir committed Apr 15, 2014
2 parents 1c2d26e + 3903145 commit 64bc907
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 48 deletions.
37 changes: 25 additions & 12 deletions dateparser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Angular DateParser 1.0.5
* Angular DateParser 1.0.7
* https://github.com/dnasir/angular-dateParser
*
* Copyright 2013, Dzulqarnain Nasir
Expand All @@ -11,13 +11,16 @@

angular.module('dateParser', [])
.factory('dateParserHelpers', [function() {

'use strict';

return {

// Returns true if string contains only integers
isJustNumbers: function(string) {
hasOnlyIntegers: function(string) {
if(!string) return false;

var digits = "1234567890";
var digits = '1234567890';

for (var i = 0; i < string.length; i++) {
if (digits.indexOf(string.charAt(i)) == -1) return false;
Expand All @@ -31,7 +34,7 @@ angular.module('dateParser', [])
for (var i = maxLength; i >= minLength; i--) {
var extracted = string.substring(startPoint, startPoint + i);

if(this.isJustNumbers(extracted)) {
if(this.hasOnlyIntegers(extracted)) {
return extracted;
}
}
Expand All @@ -41,6 +44,8 @@ angular.module('dateParser', [])
}])
.factory('$dateParser', ['$locale', 'dateParserHelpers', function($locale, dateParserHelpers) {

'use strict';

// Fetch date and time formats from $locale service
var datetimeFormats = $locale.DATETIME_FORMATS;

Expand Down Expand Up @@ -79,8 +84,8 @@ angular.module('dateParser', [])
hh = 0,
mm = 0,
ss = 0,
sss = 0,
ampm = 'am',
now = new Date(),
z = 0,
parsedZ = false;

Expand Down Expand Up @@ -115,7 +120,6 @@ angular.module('dateParser', [])
}

// Extract contents of value based on format token
// TODO: Implement millisecond (.sss or ,sss) extractor
if (token == 'yyyy' || token == 'yy' || token == 'y') {
var minLength, maxLength;

Expand Down Expand Up @@ -227,6 +231,14 @@ angular.module('dateParser', [])
}

i_val += ss.length;
} else if (token === 'sss') {
sss = dateParserHelpers.getInteger(val, i_val, 3, 3);

if (sss === null || (sss < 0) || (sss > 999)) {
throw 'Invalid milliseconds';
}

i_val += 3;
} else if (token == 'a') {
if (val.substring(i_val, i_val + 2).toLowerCase() == 'am') {
ampm = 'AM';
Expand Down Expand Up @@ -269,6 +281,7 @@ angular.module('dateParser', [])
hh = parseInt(hh);
mm = parseInt(mm);
ss = parseInt(ss);
sss = parseInt(sss);

// Is date valid for month?
if (month == 2) {
Expand Down Expand Up @@ -297,15 +310,15 @@ angular.module('dateParser', [])
hh -= 12;
}

var localDate = new Date(year, month - 1, date, hh, mm, ss);
var localDate = new Date(year, month - 1, date, hh, mm, ss, sss);

if (parsedZ) {
return new Date(localDate.getTime() + (z + localDate.getTimezoneOffset()) * 60 * 1000);
} else {
return localDate;
return new Date(localDate.getTime() - (z + localDate.getTimezoneOffset()) * 60000);
}

return localDate;
} catch(e) {
// TODO: Return undefined?
return new Date(undefined);
return undefined;
}
};
}]);
63 changes: 51 additions & 12 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,37 +39,48 @@
border-radius: 4px 0 4px 0;
}

.dn-timepicker-popup {
max-height: 300px;
overflow-y: scroll;
}
.footer {
text-align: center;
padding: 30px 0;
margin-top: 70px;
border-top: 1px solid #e5e5e5;
background-color: #f5f5f5;
}

.footer p {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="container" ng-controller="controller">
<header class="page-header">
<h1>Angular DateParser <small>Demo</small></h1>
<h1>AngularJS DateParser <small>Demo</small></h1>
</header>

<p>This parser converts date and time strings into JavaScript Date objects.</p>
<p>The AngularJS library has a <a href="http://docs.angularjs.org/api/ng/filter/date" target="_blank" title="AngularJS date filter">date filter</a> that allows JavaScript Date objects to be displayed using a provided format. This is an awesome feature, and it's great that you can use it anywhere, including text input boxes. But the problem is that it only works one-way. There's currently no way to convert strings back into Date objects while using the same format initially used to display it. This parser was designed to overcome this problem.</p>

<h4>Basic</h4>
<p>This is a basic example demonstrating how the parser can convert manually entered date strings into JavaScript Date objects.</p>

<div class="bs-docs-example">
<p>
<div class="input-prepend">
<span class="add-on">Date and time</span>
<input type="text" ng-model="date" date-parser="dd.MM.yyyy HH:mm" />
</div>
</p>
<p>Selected date: {{date | date:'MMM d, y h:m'}}</p>
<p>Selected date: {{date | date:'MMM d, y h:mm'}}</p>
</div>

<h6>Code</h6>
<div>
<pre class="brush: html">&lt;input type="text" ng-model="date" date-parser="dd.MM.yyyy HH:mm" /&gt;</pre>
</div>

<h4>Using Angular Date Formats</h4>
<p>Use all the shortname formats provided by Angular.</p>
<p>The AngularJS date filter comes with several shortname formats that you can use. The DateParser can recognise these formats and will convert the date strings accordingly.</p>

<div class="bs-docs-example">
<p>
<div class="input-prepend">
Expand Down Expand Up @@ -122,8 +133,9 @@ <h4>Using Angular Date Formats</h4>
<input type="text" ng-model="date" date-parser="shortTime" />
</div>
</p>
<p>Selected date: {{date | date:'MMM d, y h:m'}}</p>
<p>Selected date: {{date | date:'MMM d, y h:mm'}}</p>
</div>

<h6>Code</h6>
<div>
<pre class="brush: html">&lt;input type="text" ng-model="date" date-parser="medium" /&gt;
Expand All @@ -138,7 +150,8 @@ <h6>Code</h6>
</div>

<h4>Dynamic Formats</h4>
<p>Format can be dynamically changed and the view will automatically update to use the new format.</p>
<p>Date string formats can be changed on-the-fly and associated views will automatically be updated to use the new format.</p>

<div class="bs-docs-example">
<div class="input-prepend">
<span class="add-on">Format</span>
Expand All @@ -148,21 +161,47 @@ <h4>Dynamic Formats</h4>
<span class="add-on">Date</span>
<input type="text" ng-model="date" date-parser="{{format}}" />
</div>
<p>Selected date: {{date | date:'MMM d, y h:m'}}</p>
<p>Selected date: {{date | date:'MMM d, y h:mm'}}</p>
</div>

<h6>Code</h6>
<div ng-non-bindable>
<pre class="brush: html" ng->&lt;input type="text" ng-model="date" date-parser="{{format}}" /&gt;</pre>
</div>

<h4>Timezones</h4>
<p>The parser also allows you to change the timezone. However, bear in mind that the model will still contain the date and time for the local timezone, minus the offset.</p>

<div class="bs-docs-example">
<div class="input-prepend">
<span class="add-on">Date</span>
<input type="text" ng-model="date" date-parser="dd/MM/yyyy HH:mm Z" />
</div>
<p>Selected date: {{date | date:'MMM d, y h:mm Z'}}</p>
</div>

<h6>Code</h6>
<div ng-non-bindable>
<pre class="brush: html" ng->&lt;input type="text" ng-model="date" date-parser="dd/MM/yyyy HH:mm Z" /&gt;</pre>
</div>
</div>

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<footer class="footer">
<div class="container">
<p>Copyright &copy; 2014 <a href="http://dnasir.com" title="Dzulqarnain Nasir">Dzulqarnain Nasir</a></p>
<p>Code licensed under <a href="http://opensource.org/licenses/MIT" target="_blank" title="The MIT License">MIT License</a></p>
</div>
</footer>

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<script src="dateparser.js"></script>
<script src="dateparser.directive.js"></script>
<script>
function controller($scope) {
$scope.format = 'dd.MM.yyyy';
$scope.date = new Date();


}
</script>

Expand Down
68 changes: 44 additions & 24 deletions test/dateparser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ describe('dateParser', function() {

describe('helper function test', function() {
it('should return true if value given is an integer', inject(function(dateParserHelpers) {
expect(dateParserHelpers.isJustNumbers('123')).toBe(true);
expect(dateParserHelpers.isJustNumbers('123.5')).toBe(false);
expect(dateParserHelpers.isJustNumbers('abc')).toBe(false);
expect(dateParserHelpers.isJustNumbers('12:')).toBe(false);
expect(dateParserHelpers.isJustNumbers('012')).toBe(true);
expect(dateParserHelpers.isJustNumbers('0:12')).toBe(false);
expect(dateParserHelpers.isJustNumbers(null)).toBe(false);
expect(dateParserHelpers.isJustNumbers(undefined)).toBe(false);
expect(dateParserHelpers.hasOnlyIntegers('123')).toBe(true);
expect(dateParserHelpers.hasOnlyIntegers('123.5')).toBe(false);
expect(dateParserHelpers.hasOnlyIntegers('abc')).toBe(false);
expect(dateParserHelpers.hasOnlyIntegers('12:')).toBe(false);
expect(dateParserHelpers.hasOnlyIntegers('012')).toBe(true);
expect(dateParserHelpers.hasOnlyIntegers('0:12')).toBe(false);
expect(dateParserHelpers.hasOnlyIntegers(null)).toBe(false);
expect(dateParserHelpers.hasOnlyIntegers(undefined)).toBe(false);
}));

it('should return integers extracted from a string', inject(function(dateParserHelpers) {
Expand All @@ -28,16 +28,24 @@ describe('dateParser', function() {
var str1 = '17.12.2013',
str2 = '17-12-2013 12:59',
str3 = 'December 17, 2013 12:59',
str4 = '4:15 in the morning';
str4 = '4:15 in the morning',
str5 = '4/3/2014 10:45:45.345',
str6 = 'November 8, 1983 9:55pm',
str7 = '2011-04-01';

var format1 = 'dd.MM.yyyy',
format2 = 'dd-MM-yyyy HH:mm',
format3 = 'MMMM d, yyyy HH:mm',
format4 = "h:m 'in the morning'";
format4 = "h:m 'in the morning'",
format5 = 'd/M/yyyy H:mm:ss.sss',
format6 = 'MMMM d, yyyy h:mma',
format7 = 'yy-MMMM-dd';

var expected1 = new Date(2013, 11, 17, 0, 0, 0),
expected2 = new Date(2013, 11, 17, 12, 59, 0),
expected3 = new Date(2013, 11, 17, 12, 59, 0);
expected3 = new Date(2013, 11, 17, 12, 59, 0),
expected5 = new Date(2014, 2, 4, 10, 45, 45, 345),
expected6 = new Date(1983, 10, 8, 21, 55, 0);

expect($dateParser(str1, format1).getTime()).toBe(expected1.getTime());
expect($dateParser(str2, format2).getTime()).toBe(expected2.getTime());
Expand All @@ -46,34 +54,46 @@ describe('dateParser', function() {
var result4 = $dateParser(str4, format4);
expect(result4.getHours()).toBe(4);
expect(result4.getMinutes()).toBe(15);

expect($dateParser(str5, format5).getTime()).toBe(expected5.getTime());
expect($dateParser(str6, format6).getTime()).toBe(expected6.getTime());
expect($dateParser(str7, format7)).toBe(undefined);
}));

it('should properly parse timezones', inject(function($dateParser) {
var str1 = 'December 17, 2013 12:59 +0300',
str2 = 'December 17, 2013 12:59 -0300';
str2 = 'April 17, 2013 12:59 -0300',
str3 = 'December 17, 2013 12:59 +1300',
str4 = 'January 1, 2020 23:59 +1200',
str5 = 'July 1, 2020 23:59 -0700',
str6 = 'November 8, 1983 09:59 +0530';

var format = 'MMMM d, yyyy HH:mm Z';

var expectedBase = new Date(2013, 11, 17, 12, 59, 0),
expected1 = new Date(expectedBase.getTime() + (180 + expectedBase.getTimezoneOffset()) * 60 * 1000),
expected2 = new Date(expectedBase.getTime() + (-180 + expectedBase.getTimezoneOffset()) * 60 * 1000);

expect($dateParser(str1, format).getTime()).toBe(expected1.getTime());
expect($dateParser(str2, format).getTime()).toBe(expected2.getTime());
expect($dateParser(str1, format).getUTCHours()).toBe(9);
expect($dateParser(str2, format).getUTCHours()).toBe(15);
expect($dateParser(str3, format)).toBe(undefined);
expect($dateParser(str4, format).getUTCHours()).toBe(11);
expect($dateParser(str5, format).getUTCHours()).toBe(6);
expect($dateParser(str6, format).getUTCHours()).toBe(4);
expect($dateParser(str6, format).getUTCMinutes()).toBe(29);
}));

it('should return Invalid Date for invalid date strings', inject(function($dateParser) {
it('should return undefined for invalid date strings and pattern mismatches', inject(function($dateParser) {
var str1 = '29.02.2013',
str2 = '31-04-2013',
str3 = 'November 31, 2013';
str3 = 'November 31, 2013',
str4 = '12/12/2012';

var format1 = 'dd.MM.yyyy',
format2 = 'dd-MM-yyyy',
format3 = 'MMMM d, yyyy';
format3 = 'MMMM d, yyyy',
format4 = 'dd/MMMM/yy';

expect(isNaN($dateParser(str1, format1))).toBe(true);
expect(isNaN($dateParser(str2, format2))).toBe(true);
expect(isNaN($dateParser(str3, format3))).toBe(true);
expect($dateParser(str1, format1)).toBe(undefined);
expect($dateParser(str2, format2)).toBe(undefined);
expect($dateParser(str3, format3)).toBe(undefined);
expect($dateParser(str4, format4)).toBe(undefined);
}));
});

Expand Down

0 comments on commit 64bc907

Please sign in to comment.