/strftime.js

http://strftime-js.googlecode.com/ · JavaScript · 731 lines · 161 code · 23 blank · 547 comment · 30 complexity · 3c9c593ea22d399048ff8ca586f4fd9b MD5 · raw file

  1. /*
  2. strftime for Javascript
  3. Copyright (c) 2008, Philip S Tellis <philip@bluesmoon.info>
  4. All rights reserved.
  5. This code is distributed under the terms of the BSD licence
  6. Redistribution and use of this software in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice, this list of conditions
  9. and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice, this list of
  11. conditions and the following disclaimer in the documentation and/or other materials provided
  12. with the distribution.
  13. * The names of the contributors to this file may not be used to endorse or promote products
  14. derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  16. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  17. PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  18. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  19. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  21. TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  22. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. /**
  25. * \file strftime.js
  26. * \author Philip S Tellis \<philip@bluesmoon.info\>
  27. * \version 1.3
  28. * \date 2008/06
  29. * \brief Javascript implementation of strftime
  30. *
  31. * Implements strftime for the Date object in javascript based on the PHP implementation described at
  32. * http://www.php.net/strftime This is in turn based on the Open Group specification defined
  33. * at http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html This implementation does not
  34. * include modified conversion specifiers (i.e., Ex and Ox)
  35. *
  36. * The following format specifiers are supported:
  37. *
  38. * \copydoc formats
  39. *
  40. * \%a, \%A, \%b and \%B should be localised for non-English locales.
  41. *
  42. * \par Usage:
  43. * This library may be used as follows:
  44. * \code
  45. * var d = new Date();
  46. *
  47. * var ymd = d.strftime('%Y/%m/%d');
  48. * var iso = d.strftime('%Y-%m-%dT%H:%M:%S%z');
  49. *
  50. * \endcode
  51. *
  52. * \sa \link Date.prototype.strftime Date.strftime \endlink for a description of each of the supported format specifiers
  53. * \sa Date.ext.locales for localisation information
  54. * \sa http://www.php.net/strftime for the PHP implementation which is the basis for this
  55. * \sa http://tech.bluesmoon.info/2008/04/strftime-in-javascript.html for feedback
  56. */
  57. //! Date extension object - all supporting objects go in here.
  58. Date.ext = {};
  59. //! Utility methods
  60. Date.ext.util = {};
  61. /**
  62. \brief Left pad a number with something
  63. \details Takes a number and pads it to the left with the passed in pad character
  64. \param x The number to pad
  65. \param pad The string to pad with
  66. \param r [optional] Upper limit for pad. A value of 10 pads to 2 digits, a value of 100 pads to 3 digits.
  67. Default is 10.
  68. \return The number left padded with the pad character. This function returns a string and not a number.
  69. */
  70. Date.ext.util.xPad=function(x, pad, r)
  71. {
  72. if(typeof(r) == 'undefined')
  73. {
  74. r=10;
  75. }
  76. for( ; parseInt(x, 10)<r && r>1; r/=10)
  77. x = pad.toString() + x;
  78. return x.toString();
  79. };
  80. /**
  81. \brief Currently selected locale.
  82. \details
  83. The locale for a specific date object may be changed using \code Date.locale = "new-locale"; \endcode
  84. The default will be based on the lang attribute of the HTML tag of your document
  85. */
  86. Date.prototype.locale = 'en-GB';
  87. //! \cond FALSE
  88. if(document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang)
  89. {
  90. Date.prototype.locale = document.getElementsByTagName('html')[0].lang;
  91. }
  92. //! \endcond
  93. /**
  94. \brief Localised strings for days of the week and months of the year.
  95. \details
  96. To create your own local strings, add a locale object to the locales object.
  97. The key of your object should be the same as your locale name. For example:
  98. en-US,
  99. fr,
  100. fr-CH,
  101. de-DE
  102. Names are case sensitive and are described at http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
  103. Your locale object must contain the following keys:
  104. \param a Short names of days of week starting with Sunday
  105. \param A Long names days of week starting with Sunday
  106. \param b Short names of months of the year starting with January
  107. \param B Long names of months of the year starting with February
  108. \param c The preferred date and time representation in your locale
  109. \param p AM or PM in your locale
  110. \param P am or pm in your locale
  111. \param x The preferred date representation for the current locale without the time.
  112. \param X The preferred time representation for the current locale without the date.
  113. \sa Date.ext.locales.en for a sample implementation
  114. \sa \ref localisation for detailed documentation on localising strftime for your own locale
  115. */
  116. Date.ext.locales = { };
  117. /**
  118. * \brief Localised strings for English (British).
  119. * \details
  120. * This will be used for any of the English dialects unless overridden by a country specific one.
  121. * This is the default locale if none specified
  122. */
  123. Date.ext.locales.en = {
  124. a: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  125. A: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
  126. b: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  127. B: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  128. c: '%a %d %b %Y %T %Z',
  129. p: ['AM', 'PM'],
  130. P: ['am', 'pm'],
  131. x: '%d/%m/%y',
  132. X: '%T'
  133. };
  134. //! \cond FALSE
  135. // Localised strings for US English
  136. Date.ext.locales['en-US'] = Date.ext.locales.en;
  137. Date.ext.locales['en-US'].c = '%a %d %b %Y %r %Z';
  138. Date.ext.locales['en-US'].x = '%D';
  139. Date.ext.locales['en-US'].X = '%r';
  140. // Localised strings for British English
  141. Date.ext.locales['en-GB'] = Date.ext.locales.en;
  142. // Localised strings for Australian English
  143. Date.ext.locales['en-AU'] = Date.ext.locales['en-GB'];
  144. //! \endcond
  145. //! \brief List of supported format specifiers.
  146. /**
  147. * \details
  148. * \arg \%a - abbreviated weekday name according to the current locale
  149. * \arg \%A - full weekday name according to the current locale
  150. * \arg \%b - abbreviated month name according to the current locale
  151. * \arg \%B - full month name according to the current locale
  152. * \arg \%c - preferred date and time representation for the current locale
  153. * \arg \%C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
  154. * \arg \%d - day of the month as a decimal number (range 01 to 31)
  155. * \arg \%D - same as %m/%d/%y
  156. * \arg \%e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31')
  157. * \arg \%g - like %G, but without the century
  158. * \arg \%G - The 4-digit year corresponding to the ISO week number
  159. * \arg \%h - same as %b
  160. * \arg \%H - hour as a decimal number using a 24-hour clock (range 00 to 23)
  161. * \arg \%I - hour as a decimal number using a 12-hour clock (range 01 to 12)
  162. * \arg \%j - day of the year as a decimal number (range 001 to 366)
  163. * \arg \%m - month as a decimal number (range 01 to 12)
  164. * \arg \%M - minute as a decimal number
  165. * \arg \%n - newline character
  166. * \arg \%p - either `AM' or `PM' according to the given time value, or the corresponding strings for the current locale
  167. * \arg \%P - like %p, but lower case
  168. * \arg \%r - time in a.m. and p.m. notation equal to %I:%M:%S %p
  169. * \arg \%R - time in 24 hour notation equal to %H:%M
  170. * \arg \%S - second as a decimal number
  171. * \arg \%t - tab character
  172. * \arg \%T - current time, equal to %H:%M:%S
  173. * \arg \%u - weekday as a decimal number [1,7], with 1 representing Monday
  174. * \arg \%U - week number of the current year as a decimal number, starting with
  175. * the first Sunday as the first day of the first week
  176. * \arg \%V - The ISO 8601:1988 week number of the current year as a decimal number,
  177. * range 01 to 53, where week 1 is the first week that has at least 4 days
  178. * in the current year, and with Monday as the first day of the week.
  179. * \arg \%w - day of the week as a decimal, Sunday being 0
  180. * \arg \%W - week number of the current year as a decimal number, starting with the
  181. * first Monday as the first day of the first week
  182. * \arg \%x - preferred date representation for the current locale without the time
  183. * \arg \%X - preferred time representation for the current locale without the date
  184. * \arg \%y - year as a decimal number without a century (range 00 to 99)
  185. * \arg \%Y - year as a decimal number including the century
  186. * \arg \%z - numerical time zone representation
  187. * \arg \%Z - time zone name or abbreviation
  188. * \arg \%% - a literal `\%' character
  189. */
  190. Date.ext.formats = {
  191. a: function(d) { return Date.ext.locales[d.locale].a[d.getDay()]; },
  192. A: function(d) { return Date.ext.locales[d.locale].A[d.getDay()]; },
  193. b: function(d) { return Date.ext.locales[d.locale].b[d.getMonth()]; },
  194. B: function(d) { return Date.ext.locales[d.locale].B[d.getMonth()]; },
  195. c: 'toLocaleString',
  196. C: function(d) { return Date.ext.util.xPad(parseInt(d.getFullYear()/100, 10), 0); },
  197. d: ['getDate', '0'],
  198. e: ['getDate', ' '],
  199. g: function(d) { return Date.ext.util.xPad(parseInt(Date.ext.util.G(d)/100, 10), 0); },
  200. G: function(d) {
  201. var y = d.getFullYear();
  202. var V = parseInt(Date.ext.formats.V(d), 10);
  203. var W = parseInt(Date.ext.formats.W(d), 10);
  204. if(W > V) {
  205. y++;
  206. } else if(W===0 && V>=52) {
  207. y--;
  208. }
  209. return y;
  210. },
  211. H: ['getHours', '0'],
  212. I: function(d) { var I=d.getHours()%12; return Date.ext.util.xPad(I===0?12:I, 0); },
  213. j: function(d) {
  214. var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT');
  215. ms += d.getTimezoneOffset()*60000;
  216. var doy = parseInt(ms/60000/60/24, 10)+1;
  217. return Date.ext.util.xPad(doy, 0, 100);
  218. },
  219. m: function(d) { return Date.ext.util.xPad(d.getMonth()+1, 0); },
  220. M: ['getMinutes', '0'],
  221. p: function(d) { return Date.ext.locales[d.locale].p[d.getHours() >= 12 ? 1 : 0 ]; },
  222. P: function(d) { return Date.ext.locales[d.locale].P[d.getHours() >= 12 ? 1 : 0 ]; },
  223. S: ['getSeconds', '0'],
  224. u: function(d) { var dow = d.getDay(); return dow===0?7:dow; },
  225. U: function(d) {
  226. var doy = parseInt(Date.ext.formats.j(d), 10);
  227. var rdow = 6-d.getDay();
  228. var woy = parseInt((doy+rdow)/7, 10);
  229. return Date.ext.util.xPad(woy, 0);
  230. },
  231. V: function(d) {
  232. var woy = parseInt(Date.ext.formats.W(d), 10);
  233. var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay();
  234. // First week is 01 and not 00 as in the case of %U and %W,
  235. // so we add 1 to the final result except if day 1 of the year
  236. // is a Monday (then %W returns 01).
  237. // We also need to subtract 1 if the day 1 of the year is
  238. // Friday-Sunday, so the resulting equation becomes:
  239. var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1);
  240. if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4)
  241. {
  242. idow = 1;
  243. }
  244. else if(idow === 0)
  245. {
  246. idow = Date.ext.formats.V(new Date('' + (d.getFullYear()-1) + '/12/31'));
  247. }
  248. return Date.ext.util.xPad(idow, 0);
  249. },
  250. w: 'getDay',
  251. W: function(d) {
  252. var doy = parseInt(Date.ext.formats.j(d), 10);
  253. var rdow = 7-Date.ext.formats.u(d);
  254. var woy = parseInt((doy+rdow)/7, 10);
  255. return Date.ext.util.xPad(woy, 0, 10);
  256. },
  257. y: function(d) { return Date.ext.util.xPad(d.getFullYear()%100, 0); },
  258. Y: 'getFullYear',
  259. z: function(d) {
  260. var o = d.getTimezoneOffset();
  261. var H = Date.ext.util.xPad(parseInt(Math.abs(o/60), 10), 0);
  262. var M = Date.ext.util.xPad(o%60, 0);
  263. return (o>0?'-':'+') + H + M;
  264. },
  265. Z: function(d) { return d.toString().replace(/^.*\(([^)]+)\)$/, '$1'); },
  266. '%': function(d) { return '%'; }
  267. };
  268. /**
  269. \brief List of aggregate format specifiers.
  270. \details
  271. Aggregate format specifiers map to a combination of basic format specifiers.
  272. These are implemented in terms of Date.ext.formats.
  273. A format specifier that maps to 'locale' is read from Date.ext.locales[current-locale].
  274. \sa Date.ext.formats
  275. */
  276. Date.ext.aggregates = {
  277. c: 'locale',
  278. D: '%m/%d/%y',
  279. h: '%b',
  280. n: '\n',
  281. r: '%I:%M:%S %p',
  282. R: '%H:%M',
  283. t: '\t',
  284. T: '%H:%M:%S',
  285. x: 'locale',
  286. X: 'locale'
  287. };
  288. //! \cond FALSE
  289. // Cache timezone values because they will never change for a given JS instance
  290. Date.ext.aggregates.z = Date.ext.formats.z(new Date());
  291. Date.ext.aggregates.Z = Date.ext.formats.Z(new Date());
  292. //! \endcond
  293. //! List of unsupported format specifiers.
  294. /**
  295. * \details
  296. * All format specifiers supported by the PHP implementation are supported by
  297. * this javascript implementation.
  298. */
  299. Date.ext.unsupported = { };
  300. /**
  301. * \brief Formats the date according to the specified format.
  302. * \param fmt The format to format the date in. This may be a combination of the following:
  303. * \copydoc formats
  304. *
  305. * \return A string representation of the date formatted based on the passed in parameter
  306. * \sa http://www.php.net/strftime for documentation on format specifiers
  307. */
  308. Date.prototype.strftime=function(fmt)
  309. {
  310. // Fix locale if declared locale hasn't been defined
  311. // After the first call this condition should never be entered unless someone changes the locale
  312. if(!(this.locale in Date.ext.locales))
  313. {
  314. if(this.locale.replace(/-[a-zA-Z]+$/, '') in Date.ext.locales)
  315. {
  316. this.locale = this.locale.replace(/-[a-zA-Z]+$/, '');
  317. }
  318. else
  319. {
  320. this.locale = 'en-GB';
  321. }
  322. }
  323. var d = this;
  324. // First replace aggregates
  325. while(fmt.match(/%[cDhnrRtTxXzZ]/))
  326. {
  327. fmt = fmt.replace(/%([cDhnrRtTxXzZ])/g, function(m0, m1)
  328. {
  329. var f = Date.ext.aggregates[m1];
  330. return (f == 'locale' ? Date.ext.locales[d.locale][m1] : f);
  331. });
  332. }
  333. // Now replace formats - we need a closure so that the date object gets passed through
  334. var str = fmt.replace(/%([aAbBCdegGHIjmMpPSuUVwWyY%])/g, function(m0, m1)
  335. {
  336. var f = Date.ext.formats[m1];
  337. if(typeof(f) == 'string') {
  338. return d[f]();
  339. } else if(typeof(f) == 'function') {
  340. return f.call(d, d);
  341. } else if(typeof(f) == 'object' && typeof(f[0]) == 'string') {
  342. return Date.ext.util.xPad(d[f[0]](), f[1]);
  343. } else {
  344. return m1;
  345. }
  346. });
  347. d=null;
  348. return str;
  349. };
  350. /**
  351. * \mainpage strftime for Javascript
  352. *
  353. * \section toc Table of Contents
  354. * - \ref intro_sec
  355. * - <a class="el" href="strftime.js">Download full source</a> / <a class="el" href="strftime-min.js">minified</a>
  356. * - \subpage usage
  357. * - \subpage format_specifiers
  358. * - \subpage localisation
  359. * - \link strftime.js API Documentation \endlink
  360. * - \subpage demo
  361. * - \subpage changelog
  362. * - \subpage faq
  363. * - <a class="el" href="http://tech.bluesmoon.info/2008/04/strftime-in-javascript.html">Feedback</a>
  364. * - \subpage copyright_licence
  365. *
  366. * \section intro_sec Introduction
  367. *
  368. * C and PHP developers have had access to a built in strftime function for a long time.
  369. * This function is an easy way to format dates and times for various display needs.
  370. *
  371. * This library brings the flexibility of strftime to the javascript Date object
  372. *
  373. * Use this library if you frequently need to format dates in javascript in a variety of ways. For example,
  374. * if you have PHP code that writes out formatted dates, and want to mimic the functionality using
  375. * progressively enhanced javascript, then this library can do exactly what you want.
  376. *
  377. *
  378. *
  379. *
  380. * \page usage Example usage
  381. *
  382. * \section usage_sec Usage
  383. * This library may be used as follows:
  384. * \code
  385. * var d = new Date();
  386. *
  387. * var ymd = d.strftime('%Y/%m/%d');
  388. * var iso = d.strftime('%Y-%m-%dT%H:%M:%S%z');
  389. *
  390. * \endcode
  391. *
  392. * \subsection examples Examples
  393. *
  394. * To get the current time in hours and minutes:
  395. * \code
  396. * var d = new Date();
  397. * d.strftime("%H:%M");
  398. * \endcode
  399. *
  400. * To get the current time with seconds in AM/PM notation:
  401. * \code
  402. * var d = new Date();
  403. * d.strftime("%r");
  404. * \endcode
  405. *
  406. * To get the year and day of the year for August 23, 2009:
  407. * \code
  408. * var d = new Date('2009/8/23');
  409. * d.strftime("%Y-%j");
  410. * \endcode
  411. *
  412. * \section demo_sec Demo
  413. *
  414. * Try your own examples on the \subpage demo page. You can use any of the supported
  415. * \subpage format_specifiers.
  416. *
  417. *
  418. *
  419. *
  420. * \page localisation Localisation
  421. * You can localise strftime by implementing the short and long forms for days of the
  422. * week and months of the year, and the localised aggregates for the preferred date
  423. * and time representation for your locale. You need to add your locale to the
  424. * Date.ext.locales object.
  425. *
  426. * \section localising_fr Localising for french
  427. *
  428. * For example, this is how we'd add French language strings to the locales object:
  429. * \dontinclude index.html
  430. * \skip Generic french
  431. * \until };
  432. * The % format specifiers are all defined in \ref formats. You can use any of those.
  433. *
  434. * This locale definition may be included in your own source file, or in the HTML file
  435. * including \c strftime.js, however it must be defined \em after including \c strftime.js
  436. *
  437. * The above definition includes generic french strings and formats that are used in France.
  438. * Other french speaking countries may have other representations for dates and times, so we
  439. * need to override this for them. For example, Canadian french uses a Y-m-d date format,
  440. * while French french uses d.m.Y. We fix this by defining Canadian french to be the same
  441. * as generic french, and then override the format specifiers for \c x for the \c fr-CA locale:
  442. * \until End french
  443. *
  444. * You can now use any of the French locales at any time by setting \link Date.prototype.locale Date.locale \endlink
  445. * to \c "fr", \c "fr-FR", \c "fr-CA", or any other french dialect:
  446. * \code
  447. * var d = new Date("2008/04/22");
  448. * d.locale = "fr";
  449. *
  450. * d.strftime("%A, %d %B == %x");
  451. * \endcode
  452. * will return:
  453. * \code
  454. * mardi, 22 avril == 22.04.2008
  455. * \endcode
  456. * While changing the locale to "fr-CA":
  457. * \code
  458. * d.locale = "fr-CA";
  459. *
  460. * d.strftime("%A, %d %B == %x");
  461. * \endcode
  462. * will return:
  463. * \code
  464. * mardi, 22 avril == 2008-04-22
  465. * \endcode
  466. *
  467. * You can use any of the format specifiers defined at \ref formats
  468. *
  469. * The locale for all dates defaults to the value of the \c lang attribute of your HTML document if
  470. * it is set, or to \c "en" otherwise.
  471. * \note
  472. * Your locale definitions \b MUST be added to the locale object before calling
  473. * \link Date.prototype.strftime Date.strftime \endlink.
  474. *
  475. * \sa \ref formats for a list of format specifiers that can be used in your definitions
  476. * for c, x and X.
  477. *
  478. * \section locale_names Locale names
  479. *
  480. * Locale names are defined in RFC 1766. Typically, a locale would be a two letter ISO639
  481. * defined language code and an optional ISO3166 defined country code separated by a -
  482. *
  483. * eg: fr-FR, de-DE, hi-IN
  484. *
  485. * \sa http://www.ietf.org/rfc/rfc1766.txt
  486. * \sa http://www.loc.gov/standards/iso639-2/php/code_list.php
  487. * \sa http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
  488. *
  489. * \section locale_fallback Locale fallbacks
  490. *
  491. * If a locale object corresponding to the fully specified locale isn't found, an attempt will be made
  492. * to fall back to the two letter language code. If a locale object corresponding to that isn't found
  493. * either, then the locale will fall back to \c "en". No warning will be issued.
  494. *
  495. * For example, if we define a locale for de:
  496. * \until };
  497. * Then set the locale to \c "de-DE":
  498. * \code
  499. * d.locale = "de-DE";
  500. *
  501. * d.strftime("%a, %d %b");
  502. * \endcode
  503. * In this case, the \c "de" locale will be used since \c "de-DE" has not been defined:
  504. * \code
  505. * Di, 22 Apr
  506. * \endcode
  507. *
  508. * Swiss german will return the same since it will also fall back to \c "de":
  509. * \code
  510. * d.locale = "de-CH";
  511. *
  512. * d.strftime("%a, %d %b");
  513. * \endcode
  514. * \code
  515. * Di, 22 Apr
  516. * \endcode
  517. *
  518. * We need to override the \c a specifier for Swiss german, since it's different from German german:
  519. * \until End german
  520. * We now get the correct results:
  521. * \code
  522. * d.locale = "de-CH";
  523. *
  524. * d.strftime("%a, %d %b");
  525. * \endcode
  526. * \code
  527. * Die, 22 Apr
  528. * \endcode
  529. *
  530. * \section builtin_locales Built in locales
  531. *
  532. * This library comes with pre-defined locales for en, en-GB, en-US and en-AU.
  533. *
  534. *
  535. *
  536. *
  537. * \page format_specifiers Format specifiers
  538. *
  539. * \section specifiers Format specifiers
  540. * strftime has several format specifiers defined by the Open group at
  541. * http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html
  542. *
  543. * PHP added a few of its own, defined at http://www.php.net/strftime
  544. *
  545. * This javascript implementation supports all the PHP specifiers
  546. *
  547. * \subsection supp Supported format specifiers:
  548. * \copydoc formats
  549. *
  550. * \subsection unsupportedformats Unsupported format specifiers:
  551. * \copydoc unsupported
  552. *
  553. *
  554. *
  555. *
  556. * \page demo strftime demo
  557. * <div style="float:right;width:45%;">
  558. * \copydoc formats
  559. * </div>
  560. * \htmlinclude index.html
  561. *
  562. *
  563. *
  564. *
  565. * \page faq FAQ
  566. *
  567. * \section how_tos Usage
  568. *
  569. * \subsection howtouse Is there a manual on how to use this library?
  570. *
  571. * Yes, see \ref usage
  572. *
  573. * \subsection wheretoget Where can I get a minified version of this library?
  574. *
  575. * The minified version is available <a href="strftime-min.js" title="Minified strftime.js">here</a>.
  576. *
  577. * \subsection which_specifiers Which format specifiers are supported?
  578. *
  579. * See \ref format_specifiers
  580. *
  581. * \section whys Why?
  582. *
  583. * \subsection why_lib Why this library?
  584. *
  585. * I've used the strftime function in C, PHP and the Unix shell, and found it very useful
  586. * to do date formatting. When I needed to do date formatting in javascript, I decided
  587. * that it made the most sense to just reuse what I'm already familiar with.
  588. *
  589. * \subsection why_another Why another strftime implementation for Javascript?
  590. *
  591. * Yes, there are other strftime implementations for Javascript, but I saw problems with
  592. * all of them that meant I couldn't use them directly. Some implementations had bad
  593. * designs. For example, iterating through all possible specifiers and scanning the string
  594. * for them. Others were tied to specific libraries like prototype.
  595. *
  596. * Trying to extend any of the existing implementations would have required only slightly
  597. * less effort than writing this from scratch. In the end it took me just about 3 hours
  598. * to write the code and about 6 hours battling with doxygen to write these docs.
  599. *
  600. * I also had an idea of how I wanted to implement this, so decided to try it.
  601. *
  602. * \subsection why_extend_date Why extend the Date class rather than subclass it?
  603. *
  604. * I tried subclassing Date and failed. I didn't want to waste time on figuring
  605. * out if there was a problem in my code or if it just wasn't possible. Adding to the
  606. * Date.prototype worked well, so I stuck with it.
  607. *
  608. * I did have some worries because of the way for..in loops got messed up after json.js added
  609. * to the Object.prototype, but that isn't an issue here since {} is not a subclass of Date.
  610. *
  611. * My last doubt was about the Date.ext namespace that I created. I still don't like this,
  612. * but I felt that \c ext at least makes clear that this is external or an extension.
  613. *
  614. * It's quite possible that some future version of javascript will add an \c ext or a \c locale
  615. * or a \c strftime property/method to the Date class, but this library should probably
  616. * check for capabilities before doing what it does.
  617. *
  618. * \section curiosity Curiosity
  619. *
  620. * \subsection how_big How big is the code?
  621. *
  622. * \arg 26K bytes with documentation
  623. * \arg 4242 bytes minified using <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>
  624. * \arg 1477 bytes minified and gzipped
  625. *
  626. * \subsection how_long How long did it take to write this?
  627. *
  628. * 15 minutes for the idea while I was composing this blog post:
  629. * http://tech.bluesmoon.info/2008/04/javascript-date-functions.html
  630. *
  631. * 3 hours in one evening to write v1.0 of the code and 6 hours the same
  632. * night to write the docs and this manual. As you can tell, I'm fairly
  633. * sleepy.
  634. *
  635. * Versions 1.1 and 1.2 were done in a couple of hours each, and version 1.3
  636. * in under one hour.
  637. *
  638. * \section contributing Contributing
  639. *
  640. * \subsection how_to_rfe How can I request features or make suggestions?
  641. *
  642. * You can leave a comment on my blog post about this library here:
  643. * http://tech.bluesmoon.info/2008/04/strftime-in-javascript.html
  644. *
  645. * \subsection how_to_contribute Can I/How can I contribute code to this library?
  646. *
  647. * Yes, that would be very nice, thank you. You can do various things. You can make changes
  648. * to the library, and make a diff against the current file and mail me that diff at
  649. * philip@bluesmoon.info, or you could just host the new file on your own servers and add
  650. * your name to the copyright list at the top stating which parts you've added.
  651. *
  652. * If you do mail me a diff, let me know how you'd like to be listed in the copyright section.
  653. *
  654. * \subsection copyright_signover Who owns the copyright on contributed code?
  655. *
  656. * The contributor retains copyright on contributed code.
  657. *
  658. * In some cases I may use contributed code as a template and write the code myself. In this
  659. * case I'll give the contributor credit for the idea, but will not add their name to the
  660. * copyright holders list.
  661. *
  662. *
  663. *
  664. *
  665. * \page copyright_licence Copyright & Licence
  666. *
  667. * \section copyright Copyright
  668. * \dontinclude strftime.js
  669. * \skip Copyright
  670. * \until rights
  671. *
  672. * \section licence Licence
  673. * \skip This code
  674. * \until SUCH DAMAGE.
  675. *
  676. *
  677. *
  678. * \page changelog ChangeLog
  679. *
  680. * \par 1.3 - 2008/06/17:
  681. * - Fixed padding issue with negative timezone offsets in %r
  682. * reported and fixed by Mikko <mikko.heimola@iki.fi>
  683. * - Added support for %P
  684. * - Internationalised %r, %p and %P
  685. *
  686. * \par 1.2 - 2008/04/27:
  687. * - Fixed support for c (previously it just returned toLocaleString())
  688. * - Add support for c, x and X
  689. * - Add locales for en-GB, en-US and en-AU
  690. * - Make en-GB the default locale (previous was en)
  691. * - Added more localisation docs
  692. *
  693. * \par 1.1 - 2008/04/27:
  694. * - Fix bug in xPad which wasn't padding more than a single digit
  695. * - Fix bug in j which had an off by one error for days after March 10th because of daylight savings
  696. * - Add support for g, G, U, V and W
  697. *
  698. * \par 1.0 - 2008/04/22:
  699. * - Initial release with support for a, A, b, B, c, C, d, D, e, H, I, j, m, M, p, r, R, S, t, T, u, w, y, Y, z, Z, and %
  700. */