mobiscroll.util.datetime.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. (function ($, undefined) {
  2. var ms = $.mobiscroll;
  3. ms.datetime = {
  4. defaults: {
  5. shortYearCutoff: '+10',
  6. monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  7. monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  8. dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
  9. dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  10. dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
  11. amText: 'am',
  12. pmText: 'pm',
  13. getYear: function (d) { return d.getFullYear(); },
  14. getMonth: function (d) { return d.getMonth(); },
  15. getDay: function (d) { return d.getDate(); },
  16. getDate: function (y, m, d, h, i, s, u) { return new Date(y, m, d, h || 0, i || 0, s || 0, u || 0); },
  17. getMaxDayOfMonth: function (y, m) { return 32 - new Date(y, m, 32).getDate(); },
  18. getWeekNumber: function (d) {
  19. // Copy date so don't modify original
  20. d = new Date(d);
  21. d.setHours(0, 0, 0);
  22. // Set to nearest Thursday: current date + 4 - current day number
  23. // Make Sunday's day number 7
  24. d.setDate(d.getDate() + 4 - (d.getDay() || 7));
  25. // Get first day of year
  26. var yearStart = new Date(d.getFullYear(), 0, 1);
  27. // Calculate full weeks to nearest Thursday
  28. return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
  29. }
  30. },
  31. /**
  32. * Format a date into a string value with a specified format.
  33. * @param {String} format Output format.
  34. * @param {Date} date Date to format.
  35. * @param {Object} [settings={}] Settings.
  36. * @return {String} Returns the formatted date string.
  37. */
  38. formatDate: function (format, date, settings) {
  39. if (!date) {
  40. return null;
  41. }
  42. var s = $.extend({}, ms.datetime.defaults, settings),
  43. look = function (m) { // Check whether a format character is doubled
  44. var n = 0;
  45. while (i + 1 < format.length && format.charAt(i + 1) == m) {
  46. n++;
  47. i++;
  48. }
  49. return n;
  50. },
  51. f1 = function (m, val, len) { // Format a number, with leading zero if necessary
  52. var n = '' + val;
  53. if (look(m)) {
  54. while (n.length < len) {
  55. n = '0' + n;
  56. }
  57. }
  58. return n;
  59. },
  60. f2 = function (m, val, s, l) { // Format a name, short or long as requested
  61. return (look(m) ? l[val] : s[val]);
  62. },
  63. i,
  64. year,
  65. output = '',
  66. literal = false;
  67. for (i = 0; i < format.length; i++) {
  68. if (literal) {
  69. if (format.charAt(i) == "'" && !look("'")) {
  70. literal = false;
  71. } else {
  72. output += format.charAt(i);
  73. }
  74. } else {
  75. switch (format.charAt(i)) {
  76. case 'd':
  77. output += f1('d', s.getDay(date), 2);
  78. break;
  79. case 'D':
  80. output += f2('D', date.getDay(), s.dayNamesShort, s.dayNames);
  81. break;
  82. case 'o':
  83. output += f1('o', (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
  84. break;
  85. case 'm':
  86. output += f1('m', s.getMonth(date) + 1, 2);
  87. break;
  88. case 'M':
  89. output += f2('M', s.getMonth(date), s.monthNamesShort, s.monthNames);
  90. break;
  91. case 'y':
  92. year = s.getYear(date);
  93. output += (look('y') ? year : (year % 100 < 10 ? '0' : '') + year % 100);
  94. //output += (look('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
  95. break;
  96. case 'h':
  97. var h = date.getHours();
  98. output += f1('h', (h > 12 ? (h - 12) : (h === 0 ? 12 : h)), 2);
  99. break;
  100. case 'H':
  101. output += f1('H', date.getHours(), 2);
  102. break;
  103. case 'i':
  104. output += f1('i', date.getMinutes(), 2);
  105. break;
  106. case 's':
  107. output += f1('s', date.getSeconds(), 2);
  108. break;
  109. case 'a':
  110. output += date.getHours() > 11 ? s.pmText : s.amText;
  111. break;
  112. case 'A':
  113. output += date.getHours() > 11 ? s.pmText.toUpperCase() : s.amText.toUpperCase();
  114. break;
  115. case "'":
  116. if (look("'")) {
  117. output += "'";
  118. } else {
  119. literal = true;
  120. }
  121. break;
  122. default:
  123. output += format.charAt(i);
  124. }
  125. }
  126. }
  127. return output;
  128. },
  129. /**
  130. * Extract a date from a string value with a specified format.
  131. * @param {String} format Input format.
  132. * @param {String} value String to parse.
  133. * @param {Object} [settings={}] Settings.
  134. * @return {Date} Returns the extracted date.
  135. */
  136. parseDate: function (format, value, settings) {
  137. var s = $.extend({}, ms.datetime.defaults, settings),
  138. def = s.defaultValue || new Date();
  139. if (!format || !value) {
  140. return def;
  141. }
  142. // If already a date object
  143. if (value.getTime) {
  144. return value;
  145. }
  146. value = (typeof value == 'object' ? value.toString() : value + '');
  147. var shortYearCutoff = s.shortYearCutoff,
  148. year = s.getYear(def),
  149. month = s.getMonth(def) + 1,
  150. day = s.getDay(def),
  151. doy = -1,
  152. hours = def.getHours(),
  153. minutes = def.getMinutes(),
  154. seconds = 0, //def.getSeconds(),
  155. ampm = -1,
  156. literal = false, // Check whether a format character is doubled
  157. lookAhead = function (match) {
  158. var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
  159. if (matches) {
  160. iFormat++;
  161. }
  162. return matches;
  163. },
  164. getNumber = function (match) { // Extract a number from the string value
  165. lookAhead(match);
  166. var size = (match == '@' ? 14 : (match == '!' ? 20 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)))),
  167. digits = new RegExp('^\\d{1,' + size + '}'),
  168. num = value.substr(iValue).match(digits);
  169. if (!num) {
  170. return 0;
  171. }
  172. iValue += num[0].length;
  173. return parseInt(num[0], 10);
  174. },
  175. getName = function (match, s, l) { // Extract a name from the string value and convert to an index
  176. var names = (lookAhead(match) ? l : s),
  177. i;
  178. for (i = 0; i < names.length; i++) {
  179. if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
  180. iValue += names[i].length;
  181. return i + 1;
  182. }
  183. }
  184. return 0;
  185. },
  186. checkLiteral = function () {
  187. iValue++;
  188. },
  189. iValue = 0,
  190. iFormat;
  191. for (iFormat = 0; iFormat < format.length; iFormat++) {
  192. if (literal) {
  193. if (format.charAt(iFormat) == "'" && !lookAhead("'")) {
  194. literal = false;
  195. } else {
  196. checkLiteral();
  197. }
  198. } else {
  199. switch (format.charAt(iFormat)) {
  200. case 'd':
  201. day = getNumber('d');
  202. break;
  203. case 'D':
  204. getName('D', s.dayNamesShort, s.dayNames);
  205. break;
  206. case 'o':
  207. doy = getNumber('o');
  208. break;
  209. case 'm':
  210. month = getNumber('m');
  211. break;
  212. case 'M':
  213. month = getName('M', s.monthNamesShort, s.monthNames);
  214. break;
  215. case 'y':
  216. year = getNumber('y');
  217. break;
  218. case 'H':
  219. hours = getNumber('H');
  220. break;
  221. case 'h':
  222. hours = getNumber('h');
  223. break;
  224. case 'i':
  225. minutes = getNumber('i');
  226. break;
  227. case 's':
  228. seconds = getNumber('s');
  229. break;
  230. case 'a':
  231. ampm = getName('a', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
  232. break;
  233. case 'A':
  234. ampm = getName('A', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
  235. break;
  236. case "'":
  237. if (lookAhead("'")) {
  238. checkLiteral();
  239. } else {
  240. literal = true;
  241. }
  242. break;
  243. default:
  244. checkLiteral();
  245. }
  246. }
  247. }
  248. if (year < 100) {
  249. year += new Date().getFullYear() - new Date().getFullYear() % 100 +
  250. (year <= (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)) ? 0 : -100);
  251. }
  252. if (doy > -1) {
  253. month = 1;
  254. day = doy;
  255. do {
  256. var dim = 32 - new Date(year, month - 1, 32).getDate();
  257. if (day <= dim) {
  258. break;
  259. }
  260. month++;
  261. day -= dim;
  262. } while (true);
  263. }
  264. hours = (ampm == -1) ? hours : ((ampm && hours < 12) ? (hours + 12) : (!ampm && hours == 12 ? 0 : hours));
  265. var date = s.getDate(year, month - 1, day, hours, minutes, seconds);
  266. if (s.getYear(date) != year || s.getMonth(date) + 1 != month || s.getDay(date) != day) {
  267. return def; // Invalid date
  268. }
  269. return date;
  270. }
  271. };
  272. // @deprecated since 2.11.0, backward compatibility code
  273. // ---
  274. ms.formatDate = ms.datetime.formatDate;
  275. ms.parseDate = ms.datetime.parseDate;
  276. // ---
  277. })(jQuery);