(function(global, undefined) { var kafe = global.kafe, $ = kafe.dependencies.jQuery; kafe.bonify({name:'date', version:'1.2.0', obj:(function(){
var
// dictionary
_dict = {
fr: {
m: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
m3: [0,0,0,0,0,'Jun','Jul'],
w: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
d: ['1er'],
r: ['en ce moment','il y a moins d\'une minute','il y a environ une minute','il y a %n minutes','il y a environ une heure','il y a %n heures','hier','avant-hier','il y a %n jours','la semaine passée','il y a %n semaines','le mois passé','il y a %n mois']
},
en: {
m: ['January','February','March','April','May','June','July','August','September','October','November','December'],
w: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
d: ['1st','2nd','3rd','4th','5th','6th','7th','8th','9th','10th','11th','12th','13th','14th','15th','16th','17th','18th','19th','20th','21st','22nd','23rd','24th','25th','26th','27th','28th','29th','30th','31st'],
r: ['now','less than a minute ago','about a minute ago','%n minutes ago','about an hour ago','%n hours ago','yesterday','day before yesterday','%n days ago','last week','%n weeks ago','last month','%n months ago']
},
multi: {
m2: ['Ja','Fe','Mr','Al','Ma','Jn','Jl','Au','Se','Oc','No','De']
}
},
// get a valid lang
_lang = function(lang) {
return kafe.fn.lang(_dict,lang);
},
// get the 3-char month abbreviation
_m3 = function(month, lang) {
var d = _dict[_lang(lang)];
return (d.m3 && d.m3[month]) ? d.m3[month] : d.m[month].toString().substring(0,3);
},
// get the 3-char weekday abbreviation
_w3 = function(weekday, lang) {
var d = _dict[_lang(lang)];
return (d.w3 && d.w3[weekday]) ? d.w3[weekday] : d.w[weekday].toString().substring(0,3);
},
// trim every element of the array
_trim = function(list, nb) {
var d = [];
for (var i in list) {
d.push(list[i].toString().substr(0,nb));
}
return d;
}
;
/**
* ### Version 1.2.0
* Additionnal methods for date manipulation
*
* @module kafe
* @class kafe.date
*/
var date = {
/**
* Number of milliseconds in a second (1000 ms per second)
*
* @property SECOND
* @type Number
**/
SECOND:1000,
/**
* Number of milliseconds in a minute (60 seconds per minute)
*
* @property MINUTE
* @type Number
**/
MINUTE:60000,
/**
* Number of milliseconds in an hour (60 minutes per hour)
*
* @property HOUR
* @type Number
**/
HOUR:3600000,
/**
* Number of milliseconds in a day (24 hours per day)
*
* @property DAY
* @type Number
**/
DAY:86400000,
/**
* Number of milliseconds in a week (7 days per week)
*
* @property WEEK
* @type Number
**/
WEEK:604800000,
/**
* Number of milliseconds in a month (4.348121428571429 weeks per month)
*
* @property MONTH
* @type Number
**/
MONTH:2629743840,
/**
* Number of milliseconds in a year (365.2422 days per year)
*
* @property YEAR
* @type Number
**/
YEAR:31556926080
};
/**
* Get the day number out of the full year (365 days).
*
* @method getDayYear
* @param {Date} d The date
* @return {Number} The day of the year
* @example
* kafe.date.getDayYear(new Date('2013-07-17'));
* // returns 198
*/
date.getDayYear = function(d) {
var
max = this.getMaxMonth(d.getFullYear()),
m = d.getMonth(),
total = 0
;
for (var i=0; i<m; ++i) {
total += max[i];
}
return total+d.getDate();
};
/**
* Returns whether the date is within a leap year or not.
*
* @method isLeapYear
* @param {Number} year The year.
* @return {Boolean} If it is a leap year or not.
* @example
* kafe.date.isLeapYear(2013);
* // returns false
* @example
* kafe.date.isLeapYear(2004);
* // returns true
*/
date.isLeapYear = function(year) {
return ((year%4 === 0 && year%400 !== 0) || year == 2000);
};
/**
* Get the number of days for all the months of a given year.
*
* @method getMaxMonth
* @param {Number} year The year.
* @return {Array(Number)} An ordered array of day counts for each months of the given year.
* @example
* kafe.date.getMaxMonth(2013);
* // returns [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
* @example
* kafe.date.getMaxMonth(2013)[3];
* // returns 30
*/
date.getMaxMonth = function(year) {
return [31, (this.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
};
/**
* Get the full name of the months of the year.
*
* @method getMonthNames
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of month names.
* @example
* kafe.date.getMonthNames('en');
* // returns ["January", "February", "March", "April", "May", "June", ... ]
* @example
* kafe.date.getMonthNames('en')[3];
* // returns "April"
*/
date.getMonthNames = function(lang) {
return _dict[_lang(lang)].m;
};
/**
* Get the 1-char abbreviations of the months of the year.
*
* @method getMonth1Names
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of 1-char month abbreviations.
* @example
* kafe.date.getMonth1Names('en');
* // returns ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"]
* @example
* kafe.date.getMonth1Names('en')[3];
* // returns "A"
*/
date.getMonth1Names = function(lang) {
return _trim(_dict[_lang(lang)].m,1);
};
/**
* Get the 2-char abbreviations of the months of the year.
*
* @method getMonth2Names
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of 2-char month abbreviations.
* @example
* kafe.date.getMonth2Names('en');
* // returns ["Ja", "Fe", "Mr", "Al", "Ma", "Jn", "Jl", "Au", "Se", "Oc", "No", "De"]
* @example
* kafe.date.getMonth2Names('en')[3];
* // returns "Al"
*/
date.getMonth2Names = function(lang) {
lang = _lang(lang);
return (_dict[lang].m2) ? _dict[lang].m2 : _dict.multi.m2;
};
/**
* Get the 3-char abbreviations of the months of the year.
*
* @method getMonth3Names
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of 3-char month abbreviations.
* @example
* kafe.date.getMonth3Names('en');
* // returns ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
* @example
* kafe.date.getMonth3Names('en')[3];
* // returns "Apr"
*/
date.getMonth3Names = function(lang) {
var d = [];
for (var i=0; i<12; ++i) {
d.push(_m3(i, lang));
}
return d;
};
/**
* Returns whether the date is within a weekend.
*
* @method isWeekend
* @param {Date} d The date
* @return {Boolean} If it is within a weekend or not.
* @example
* kafe.date.isWeekend(new Date('2013-07-17'));
* // returns false
* @example
* kafe.date.isWeekend(new Date('2013-07-20'));
* // returns true
*/
date.isWeekend = function(date) {
var weekday = date.getDay();
return (weekday === 0 || weekday === 6);
};
/**
* Get the full name of the days of the week.
*
* @method getWeekdayNames
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of weekday names.
* @example
* kafe.date.getWeekdayNames('en');
* // returns ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
* @example
* kafe.date.getWeekdayNames('en')[3];
* // returns "Wednesday"
*/
date.getWeekdayNames = function(lang) {
return _dict[_lang(lang)].w;
};
/**
* Get the 1-char abbreviations of the days of the week.
*
* @method getWeekday1Names
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of 1-char weekday abbreviations.
* @example
* kafe.date.getWeekday1Names('en');
* // returns ["S", "M", "T", "W", "T", "F", "S"]
* @example
* kafe.date.getWeekday1Names('en')[3];
* // returns "W"
*/
date.getWeekday1Names = function(lang) {
return _trim(_dict[_lang(lang)].w,1);
};
/**
* Get the 2-char abbreviations of the days of the week.
*
* @method getWeekday2Names
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of 2-char weekday abbreviations.
* @example
* kafe.date.getWeekday2Names('en');
* // returns ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
* @example
* kafe.date.getWeekday2Names('en')[3];
* // returns "We"
*/
date.getWeekday2Names = function(lang) {
return _trim(_dict[_lang(lang)].w,2);
};
/**
* Get the 3-char abbreviations of the days of the week.
*
* @method getWeekday3Names
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of 3-char weekday abbreviations.
* @example
* kafe.date.getWeekday3Names('en');
* // returns ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
* @example
* kafe.date.getWeekday3Names('en')[3];
* // returns "Wed"
*/
date.getWeekday3Names = function(lang) {
var d = [];
for (var i=0; i<7; ++i) {
d.push(_w3(i, lang));
}
return d;
};
/**
* Get a clean representation for all possible days of a month.
*
* @method getDayNames
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {Array(String)} An ordered array of clean representations for all possible days of a month.
* @example
* kafe.date.getDayNames('en');
* // returns ["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", ... ]
* @example
* kafe.date.getDayNames('en')[3];
* // returns "4th"
*/
date.getDayNames = function(lang) {
var
d = _dict[_lang(lang)].d,
l = d.length
;
for (var i=l; i<31; ++i) {
d[i] = (i+1).toString();
}
return d;
};
/**
* Flexible formatting a given date object.
*
* @method format
* @param {String} format A custom format composed of %- tokens. Characters that are not part of a token will be rendered literally.
* @param {Token} format.%Y,%y Year variants: [2011, 11]
* @param {Token} format.%M,%m,%A,%a,%B,%b,%C,%c Month variants: [01, 1, January, january, Jan, jan, JA, Ja]
* @param {Token} format.%D,%d,%e Day variants: [02, 2, 2nd]
* @param {Token} format.%W,%w,%X,%x,%Z,%z Weekday variants: [Sunday, sunday, Sun, sun, Su, su]
* @param {Token} format.%H,%h,%K,%k,%p Hour variants [15, 15, 03, 3, pm]
* @param {Token} format.%I,%i Minute variants [04, 4]
* @param {Token} format.%S,%s Second variants [05, 5]
* @param {Date} [date=NOW] A date to be formatted.
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {String} The formatted date.
* @example
* kafe.date.format('%W, %A %e, %Y', new Date('2013-07-17'), 'en');
* // returns "Tuesday, July 16th, 2013"
* @example
* kafe.date.format('%W, %d %a, %Y', new Date('2013-07-17'), 'fr');
* // returns "Mardi, 16 juillet, 2013"
*/
date.format = function(format, date, lang) {
date = (date) ? date : new Date();
lang = _lang(lang);
var
pad = function() { return ('0'+arguments[0].toString()).slice(-2); },
d = _dict[lang],
year = date.getFullYear(),
month = date.getMonth()+1,
day = date.getDate(),
weekday = date.getDay(),
hours = date.getHours(),
minutes = date.getMinutes(),
seconds = date.getSeconds(),
hours12 = ((hours % 12) === 0) ? 12 : (hours % 12),
hoursAmPm = Math.floor(hours/12),
// 2011-01-02 15:04:05
data = { // -------------------
Y: year, // year 2011
y: year.toString().substring(2), // year 11
M: pad(month), // month 01
m: month, // month 1
A: d.m[month-1], // month January
a: d.m[month-1].toLowerCase(), // month january
B: this.getMonth3Names(lang)[month-1], // month Jan
b: this.getMonth3Names(lang)[month-1].toLowerCase(), // month jan
C: this.getMonth2Names(lang)[month-1].toUpperCase(), // month JA
c: this.getMonth2Names(lang)[month-1], // month Ja
D: pad(day), // day 02
d: day, // day 2
e: this.getDayNames(lang)[day-1], // day 2nd
W: d.w[weekday], // weekday Sunday
w: d.w[weekday].toLowerCase(), // weekday sunday
X: this.getWeekday3Names(lang)[weekday], // weekday Sun
x: this.getWeekday3Names(lang)[weekday].toLowerCase(), // weekday sun
Z: this.getWeekday2Names(lang)[weekday], // weekday Su
z: this.getWeekday2Names(lang)[weekday].toLowerCase(), // weekday su
H: pad(hours), // hour 15
h: hours, // hour 15
K: pad(hours12), // hour 03
k: hours12, // hour 3
p: (hoursAmPm) ? 'pm' : 'am', // hour pm
I: pad(minutes), // minute 04
i: minutes, // minute 4
S: pad(seconds), // second 05
s: seconds // second 5
}
;
for (var i in data) {
format = format.replace(new RegExp('%'+i,'g'),data[i]);
}
return format;
};
/**
* Get a relative time expression from a specific datetime.
*
* @method formatRelative
* @param {Date} time Specific datetime object.
* @param {Date} [now=NOW] Comparative datetime object to calculate the time difference.
* @param {String} [lang=CURRENT_ENV_LANG] A two character language code.
* @return {String} The relative time expression
* @example
* kafe.date.formatRelative(new Date('2013-07-19 6:00:00'), new Date('2013-07-19 20:00:00'), 'en');
* // returns "14 hours ago"
* @example
* kafe.date.formatRelative(new Date('2013-05-19'), new Date('2013-07-19'), 'en');
* // returns "2 months ago"
*/
date.formatRelative = function(time, now, lang) {
now = (now) ? now : new Date();
var
d = _dict[_lang(lang)].r,
delta = now.getTime() - time.getTime()
;
if (delta <= 0) {
return d[0];
} else if (delta < date.MINUTE) {
return d[1];
} else if(delta < 2*date.MINUTE) {
return d[2];
} else if(delta < date.HOUR) {
return d[3].replace('%n', Math.floor(delta/date.MINUTE));
} else if(delta < 2*date.HOUR) {
return d[4];
} else if(delta < date.DAY) {
return d[5].replace('%n', Math.floor(delta/date.HOUR));
} else if(delta < 2*date.DAY) {
return d[6];
} else if(delta < 3*date.DAY) {
return d[7];
} else if(delta < date.WEEK) {
return d[8].replace('%n', Math.floor(delta/date.DAY));
} else if(delta < 2*date.WEEK) {
return d[9];
} else if(delta < date.MONTH) {
return d[10].replace('%n', Math.floor(delta/date.WEEK));
} else if(delta < 2*date.MONTH) {
return d[11];
} else {
return d[12].replace('%n', Math.floor(delta/date.MONTH));
}
};
/**
* Parses a given datetime string into a standard datetime object.
*
* @method parse
* @param {String} dtstring Custom datetime string
* @return {Date} The date object
* @example
* kafe.date.parse('2012-08-08T12:18:00.000-04:00');
* // returns Wed Aug 08 2012 12:18:00 GMT-0400 (EDT)
* @example
* kafe.date.parse('June 3, 2013');
* // returns Mon Jun 03 2013 00:00:00 GMT-0400 (EDT)
*/
date.parse = function(dtstring) {
if (/^([0-9]{2,4})-([0-9]{2})-([0-9]{2})$/gi.test(dtstring)) {
dtstring += ' 00:00:00';
} else if (/^([0-9]{2,4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2})$/gi.test(dtstring)) {
dtstring += ':00';
}
var ts = Date.parse(dtstring);
if (isNaN(ts)) {
var
y2y4 = function(year) {
if (year > 69 && year < 100) {
return Number(year) + 1900;
} else if (year < 69) {
return Number(year) + 2000;
} else {
return year;
}
},
m = date.getMonth3Names('en'),
year, month, day, hour, minute, second, delta, e, d
;
// ISO 8601 / 2011-03-08 09:25:15 (useless for chrome)
if ((e = new RegExp('^([0-9]{2,4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$','gi').exec(dtstring))) {
year = y2y4(e[1]);
month = e[2];
day = e[3];
hour = e[4];
minute = e[5];
second = e[6];
// RFC 822 (rss) / Sat, 30 Oct 10 13:51:32 +0000
} else if ((e = new RegExp('^([a-z]{3}), ([0-9]{2}) ([a-z]{3}) ([0-9]{2,4}) ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+-][0-9]{4})$','gi').exec(dtstring))) {
year = y2y4(e[4]);
month = $.inArray(e[3], m)+1;
day = e[2];
hour = e[5];
minute = e[6];
second = e[7];
delta = e[8]/100;
// (twitter) / Mon Nov 01 01:49:22 +0000 2010
} else if ((e = new RegExp('^([a-z]{3}) ([a-z]{3}) ([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+-][0-9]{4}) ([0-9]{2,4})$','gi').exec(dtstring))) {
year = y2y4(e[8]);
month = $.inArray(e[2], m)+1;
day = e[3];
hour = e[4];
minute = e[5];
second = e[6];
delta = e[7]/100;
// ISO 8601 / 2012-08-08T12:18:00.000-04:00 (useless for chrome/safari)
} else if ((e = new RegExp('^([0-9]{2,4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\\.([0-9]{3})([+-])([0-9]{2}):([0-9]{2})$','gi').exec(dtstring))) {
year = y2y4(e[1]);
month = e[2];
day = e[3];
hour = e[4];
minute = e[5];
second = e[6];
delta = (Number(e[9]) + (Number(e[10])/60)) * ((e[8] == '-') ? -1 : 1);
}
d = new Date(year, month-1, day, hour, minute, second, 0);
return (delta !== undefined) ? new Date(d - ( (d.getTimezoneOffset() + (Number(delta)*60) ) * 60 * 1000)) : d;
} else {
return new Date(ts);
}
};
/**
* Refreshes a dropdown containing the days of a given year/month combination.
*
* @method refreshSelectDays
* @param {DOMElement} obj The <select> element
* @param {Number} month The month
* @param {Number} year The year
* @example
* $('.select-month').on('change', function(e) {
* kafe.date.refreshSelectDays('.select-day', $(this).val(), $('.select-year').val());
* })
*/
date.refreshSelectDays = function(obj, month, year) {
// if a title in the dropdown
var
dp = (Number(obj.options[0].value)) ? 0 : 1,
dn = -dp,
nb = this.getMaxMonth(year)[month-1]
;
// if there are less day in the new month
if (obj.length+dn > nb) {
// if a impossible day for the new days is selected
if (obj.selectedIndex+1 > nb+dn) {
obj.selectedIndex = nb-1+dp;
}
obj.length = nb+dp;
// if there are more days in the new month
} else if ( obj.length+dn < nb ) {
var curr = obj.length;
obj.length = nb+dp;
// rebuild the new days
for (var i=curr; i<nb+dp; ++i) {
obj.options[i].text = i+1+dn;
obj.options[i].value = i+1+dn;
}
}
};
/**
* Creates an html table calendar for a given month/year combination. You can also provide specific dates with destination url to be included in the rendered source.
*
* @method makeMonthCalendar
* @param {Number} year The year
* @param {Number} month The month
* @param {Object} [links] The links by date
* @param {Array} links.YYYY-MM-DD The links
* @return {String} The rendered HTML
* @example
* kafe.date.makeMonthCalendar(2013, 4, {'2013-04-03':'http://mybirthday.com/'});
* // returns "<table data-month="2013-04"><caption>Avril 2013</caption><thead><tr><th>Dim</th><th>Lun</th><th>Mar</th><th>Mer</th><th>Jeu</th><th>Ven</th><th>Sam</th></thead><tbody><tr><td> </td><td data-date="2013-04-01"><span>1</span></td><td data-date="2013-04-02"><span>2</span></td><td data-date="2013-04-03"><a href="http://mybirthday.com/">3</a></td><td data-date="2013-04-04"><span>4</span></td><td data-date="2013-04-05"><span>5</span></td><td data-date="2013-04-06"><span>6</span></td></tr><tr><td data-date="2013-04-07"><span>7</span></td><td data-date="2013-04-08"><span>8</span></td><td data-date="2013-04-09"><span>9</span></td><td data-date="2013-04-10"><span>10</span></td><td data-date="2013-04-11"><span>11</span></td><td data-date="2013-04-12"><span>12</span></td><td data-date="2013-04-13"><span>13</span></td></tr><tr><td data-date="2013-04-14"><span>14</span></td><td data-date="2013-04-15"><span>15</span></td><td data-date="2013-04-16"><span>16</span></td><td data-date="2013-04-17"><span>17</span></td><td data-date="2013-04-18"><span>18</span></td><td data-date="2013-04-19"><span>19</span></td><td data-date="2013-04-20"><span>20</span></td></tr><tr><td data-date="2013-04-21"><span>21</span></td><td data-date="2013-04-22"><span>22</span></td><td data-date="2013-04-23"><span>23</span></td><td data-date="2013-04-24"><span>24</span></td><td data-date="2013-04-25"><span>25</span></td><td data-date="2013-04-26"><span>26</span></td><td data-date="2013-04-27"><span>27</span></td></tr><tr><td data-date="2013-04-28"><span>28</span></td><td data-date="2013-04-29"><span>29</span></td><td data-date="2013-04-30"><span>30</span></td><td> </td><td> </td><td> </td><td> </td></tr></tbody></table>"
*/
date.makeMonthCalendar = function(year, month, links) {
links = links || {};
--m;
var
i,
weekdays = date.getWeekday3Names(),
max = date.getMaxMonth(year)[month],
firstDay = new Date(year,month,1).getDay(),
week = 0,
today = date.format('%Y-%M-%D', new Date()),
html = '<table data-month="'+date.format('%Y-%M', new Date(year,month,1))+'"><caption>'+date.getMonthNames()[month]+' '+year+'</caption><thead><tr>'
;
// weekdays
for (i in weekdays) {
html += '<th>'+weekdays[i]+'</th>';
}
html += '</thead><tbody><tr>';
// start padding
for (i=0; i<firstDay; ++i) {
html += '<td> </td>';
++week;
}
// days
for (i=1; i<=max; ++i) {
if (week == 7) {
html += '</tr><tr>';
week = 0;
}
var thisDate = date.format('%Y-%M-%D', new Date(year,month,i));
html += '<td data-date="'+thisDate+'"'+((thisDate == today) ? ' class="Today"' : '')+'>' + ((links[thisDate]) ? '<a href="'+links[thisDate]+'">'+i+'</a>' : '<span>'+i+'</span>') + '</td>';
++week;
}
// end padding
for (i=week; i<7; ++i) {
html += '<td> </td>';
}
return html+'</tr></tbody></table>';
};
return date;
})()}); })(typeof window !== 'undefined' ? window : this);