Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Format #5

Merged
merged 4 commits into from

1 participant

Commits on Jan 10, 2013
  1. stub format test file

    authored
Commits on Jan 15, 2013
Commits on Jan 16, 2013
  1. tests for #format

    authored
This page is out of date. Refresh to see the latest.
View
123 test/format.js
@@ -0,0 +1,123 @@
+time = require('../time');
+
+describe('Time', function() {
+ describe('#format', function() {
+ it('should work with no params', function() {
+ var t = time('1:23p');
+ t.format().should.equal('1:23 pm');
+ });
+
+ it('should always require hours', function() {
+ var t = time('1.23');
+ t.format(':mm').should.equal('invalid format');
+ });
+
+ it('should not require a separator', function() {
+ var t = time('7:23');
+ t.format('hmm').should.equal('723');
+ t.format('hhmm').should.equal('0723');
+ });
+
+ it('should respect h vs hh', function() {
+ var t = time('3:20');
+ t.format('h:mm').should.equal('3:20');
+ t.format('hh:mm').should.equal('03:20');
+ });
+
+ it('should still show hh when hour is > 9', function() {
+ var t = time('12:20');
+ t.format('h:mm').should.equal('12:20');
+ });
+
+ it('should not be case sensitive for hours and minutes', function() {
+ var t = time('03:23 pm');
+ var expected = '03:23';
+ t.format('hh:mm').should.equal(expected);
+ t.format('HH:mm').should.equal(expected);
+ t.format('Hh:Mm').should.equal(expected);
+ t.format('hH:MM').should.equal(expected);
+ t.format('H:MM').should.equal('3:23');
+ });
+
+ it('should not care if a or p is used for period', function() {
+ var t = time('9p');
+ t.format('h:mm p.m.').should.equal('9:00 p.m.');
+ t.format('h:mm a.m.').should.equal('9:00 p.m.');
+ });
+
+ it('should respect case for period', function() {
+ var t = time('9p');
+ t.format('h p').should.equal('9 p');
+ t.format('h P').should.equal('9 P');
+ t.format('h Pm').should.equal('9 Pm');
+ t.format('h a.m.').should.equal('9 p.m.');
+ });
+
+ it('should respect space between period', function() {
+ var t = time('12am');
+ t.format('h:mm pm').should.equal('12:00 am');
+ t.format('h:mmam').should.equal('12:00am');
+ t.format('h a.').should.equal('12 a.');
+ t.format('hP').should.equal('12A');
+ });
+
+ it('should ignore period if not originally parsed', function() {
+ var t = time('1');
+ t.format('hpm').should.equal('1');
+ t.format('h:mm PM').should.equal('1:00');
+ });
+
+ it('should hide period if not requested', function() {
+ var t = time('1p');
+ t.format('h').should.equal('1');
+ t.format('h:mm').should.equal('1:00');
+ });
+
+ it('should hide minutes if just an hour is given', function() {
+ var t = time('12');
+ t.format('h').should.equal('12');
+ t = time('12:23');
+ t.format('h').should.equal('12');
+ });
+
+ it('should show auto-hide minutes if they are omitted but a middlebit \
+ is supplied', function() {
+ var t = time('12 pm');
+ t.format('h:').should.equal('12');
+ t.format('h:A').should.equal('12P');
+ t = time('12:23 pm');
+ t.format('h:').should.equal('12:23');
+ t.format('h.').should.equal('12.23');
+ t.format('h.P').should.equal('12.23P');
+ });
+
+ it('should respect periods on period e.g. a.m. vs am', function() {
+ var t = time('7p');
+ t.format('h:mm a').should.equal('7:00 p');
+ t.format('h:mm a.').should.equal('7:00 p.');
+ t.format('h:mm a.m.').should.equal('7:00 p.m.');
+ t.format('h:mm am').should.equal('7:00 pm');
+ t.format('h:mm am.').should.equal('7:00 pm.');
+ t.format('h:mm a.m').should.equal('7:00 p.m');
+ });
+
+ it('should allow for only first letter of period', function() {
+ var t = time('10:55 PM');
+ t.format('hh:mm A').should.equal('10:55 P');
+ t.format('hh:mm AM').should.equal('10:55 PM');
+ });
+
+ it('should only allow blank, period, or colon for seperator', function() {
+ var t = time('323');
+ t.format('hmm').should.equal('323');
+ t.format('h:mm').should.equal('3:23');
+ t.format('h.mm').should.equal('3.23');
+ t.format('h,mm').should.equal('invalid format');
+ });
+
+ it('should not allow a single minute', function() {
+ var t = time('12:30');
+ t.format('h:m').should.equal('invalid format');
+ });
+ });
+});
View
0  test/time.test.js → test/parsing.js
File renamed without changes
View
127 time.js
@@ -1,10 +1,12 @@
-(function() {
+(function () {
- var am = 'am'
- , pm = 'pm'
- , periodRegex = new RegExp('([ap]\\.?(m\\.?)?)', 'i')
- , timeRegex = new RegExp('^(10|11|12|[1-9])(?::|\\.)?([0-5][0-9])?'
- + periodRegex.source + '?$', 'i');
+ var AM = 'am'
+ , PM = 'pm'
+ , periodRegex = new RegExp('([ap](\\.?)(m\\.?)?)', 'i')
+ , timeRegex = new RegExp('^(10|11|12|0?[1-9])(?::|\\.)?([0-5][0-9])?'
+ + periodRegex.source + '?$', 'i')
+ , formatRegex = new RegExp('^(h|hh)([:|\.])?(mm)?( ?)'
+ + periodRegex.source + '?$', 'i');
// play nice with both node.js and browser
if (typeof module !== 'undefined' && module.exports) module.exports = Time;
@@ -34,7 +36,7 @@
// set to current time
var d = new Date();
hours = d.getHours();
- period = hours > 11 ? pm : am;
+ period = hours > 11 ? PM : AM;
if (hours > 12) hours -= 12;
if (hours === 0) hours = 12;
minutes = d.getMinutes();
@@ -44,19 +46,19 @@
this.hours = function(newHours) {
if (!newHours) return hours;
hours = parseInt(newHours);
- }
+ };
// gets or sets minutes
this.minutes = function(newMinutes) {
if (!newMinutes) return minutes;
minutes = parseInt(newMinutes);
- }
+ };
// gets or sets period
this.period = function(newPeriod) {
if (!newPeriod) return period;
period = parsePeriod(newPeriod);
- }
+ };
}
/*
@@ -71,7 +73,7 @@
if (!this.isValid()) return null;
var hours = this.hours() === 12 ? 0 : this.hours(); // uniformly handle am/pm adjustments
- if (this.period() === pm) hours += 12;
+ if (this.period() === PM) hours += 12;
var d = new Date();
d.setHours(hours);
d.setMinutes(this.minutes());
@@ -82,39 +84,108 @@
while (new Date() > d) d.setHours(d.getHours() + 12);
// make sure we're in the correct period
- if (d.getHours() > 11 && this.period() === am) d.setHours(d.getHours() + 12)
- else if (d.getHours() < 12 && this.period() === pm) d.setHours(d.getHours() + 12)
+ if (d.getHours() > 11 && this.period() === AM) d.setHours(d.getHours() + 12)
+ else if (d.getHours() < 12 && this.period() === PM) d.setHours(d.getHours() + 12)
return d;
- }
+ };
Time.isValid = function(time) {
return timeRegex.test(sanitize(time));
- }
+ };
Time.prototype.isValid = function() {
return Time.isValid(toString(this));
- }
+ };
/*
- * h:mm
+ * This can be safely changed if so desired.
*/
- Time.prototype.toString = function() {
- if (!this.isValid()) return 'invalid time'
- return toString(this);
- }
+ Time.DEFAULT_TIME_FORMAT = 'h:mm am';
+
+ /*
+ * Formats the time to the given format, or h:mm if one is not provided.
+ *
+ * If periods are specified in the format, they are only printed if known.
+ *
+ * If the time isn't valid, return 'invalid time'.
+ * If the format isn't valid, return 'invalid format'.
+ *
+ * This isn't every combination, but hopefully you get the gist of things.
+ * h:mm 12:00 (default)
+ * hh:mm 01:00
+ * h 1
+ * h 1:55 (input specified minutes, so we show them)
+ * h. 1.55 (if minutes are shown, use . for separator)
+ * hpm 1am
+ * h:mm a 1:55 p
+ * h:mm a 1:55 (input didn't specify period)
+ * h.mm am 1.55 pm
+ * h.mm A 1.55 P
+ * hh:mm a.m. 01:55 a.m.
+ * h:mma 1:55a
+ * h.mm 1.55
+ */
+ Time.prototype.format = function(format) {
+ format = format || Time.DEFAULT_TIME_FORMAT;
+ if (!this.isValid()) {
+ return 'invalid time';
+ } else if (!formatRegex.test(format)) {
+ return 'invalid format';
+ }
+ return toString(this, format);
+ };
+
+ /*
+ * Alias for `format`.
+ */
+ Time.prototype.toString = Time.prototype.format;
/*
- * (private) Format Time into hh:mm for validation test.
+ * (private) Format Time in the given format.
*
* @time Time instance
* @retun hh:mm e.g. 3:00, 12:23, undefined:undefined
*/
- function toString(time) {
- var minutes = time.minutes() < 10 ? '0' + time.minutes() : time.minutes()
- , result = time.hours() + ':' + minutes;
+ function toString(time, format) {
+ format = format || Time.DEFAULT_TIME_FORMAT;
+ var bits = formatRegex.exec(format);
+ var fHour = bits[1];
+ var fMiddlebit = bits[2];
+ var fMinutes = bits[3];
+ var fPeriodSpace = bits[4];
+ var fPeriod = bits[5];
+ var fFirstPeriod = bits[6];
+ var fPeriodM = bits[7];
+
+ // always show hour
+ var hours = fHour.length == 2 ? padTime(time.hours()) : time.hours();
+
+ // show if in the format or if non-zero and middlebit is provided
+ var minutes = (fMinutes || (fMiddlebit && time.minutes() !== 0)) ?
+ padTime(time.minutes()) : '';
+
+ // show middlebit if we have minutes
+ var middlebit = (minutes && fMiddlebit) ? fMiddlebit : '';
+
+ // show period if available and requested
+ var period = '';
+ if (fPeriod && time.period()) {
+ var firstPeriod = time.period().charAt(0);
+ if (fPeriod.charAt(0) === fPeriod.charAt(0).toUpperCase()) {
+ firstPeriod = firstPeriod.toUpperCase();
+ }
+ period = firstPeriod + fPeriod.slice(1);
+ }
+
+ // only show space if it was requested by format and there's a period
+ var space = (period && fPeriodSpace) ? fPeriodSpace : '';
+
+ return '' + hours + middlebit + minutes + space + period;
+ }
- return (time.period() == undefined) ? result : result + ' ' + time.period();
+ function padTime(time) {
+ return time < 10 ? '0' + time : time;
}
/*
@@ -132,7 +203,7 @@
*/
function parsePeriod(period) {
if (!period || !period.match(periodRegex)) return null;
- else if (period.match(/^p/i) != null) return pm;
- return (period.match(/^a/i) != null) ? am : null;
+ else if (period.match(/^p/i) != null) return PM;
+ return (period.match(/^a/i) != null) ? AM : null;
}
})();
Something went wrong with that request. Please try again.