Posted By

rolandog on 02/12/10


Tagged

javascript time timer elapsed ecmascript


Versions (?)

Timer.js


 / Published in: JavaScript
 

URL: http://rolandog.com/timer-js/

A constructor that takes a date and returns a Timer object with several calculations. You can enter a string, or number by number or even use it as a counter by calling it as new Timer().

  1. "use strict";
  2.  
  3. /*jslint white: true, browser: true, onevar: true, undef: true, eqeqeq: true,
  4. plusplus: true, bitwise: true, strict: true, newcap: true, immed: true,
  5. maxlen: 200 */
  6.  
  7. /*global window: true */
  8.  
  9. /**
  10.  * Timer.js
  11.  * http://rolandog.com
  12.  *
  13.  * License: Creative Commons Attribution-Share Alike 3.0 Unported.
  14.  * http://creativecommons.org/licenses/by-sa/3.0/
  15.  *
  16.  * @projectDescription Performs calculations on how much time has passed.
  17.  * @author Rolando Garza [email protected]
  18.  */
  19.  
  20. /**
  21.  * A constructor that takes a date and returns a Timer object
  22.  * with several calculations. You can enter a string, or number by number or
  23.  * even use it as a counter by calling it as new Timer().
  24.  * @param(String) YYYY A String formatted like YYYY/MM/DD HH:MM:SS.ms
  25.  */
  26. var Timer = function Timer(YYYY, MM, DD, hh, mm, ss, ms) {
  27. //rounds a date: from 2009/08/21 14:42.123 you'll get 2009/08/21
  28. function round(d) {
  29. return new Date("" + d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate());
  30. }
  31. function properties(d) {
  32. return {
  33. Y: d.getFullYear(),
  34. M: d.getMonth(),
  35. D: d.getDate(),
  36. h: d.getHours(),
  37. m: d.getMinutes(),
  38. s: d.getSeconds(),
  39. ms: d.getMilliseconds(),
  40. t: d.getTime(),
  41. d: d
  42. };
  43. }
  44. this.exactly = {};
  45. this.rounded = {};
  46. //variable declarations
  47. var start, date, Counter, ww;
  48. //start is the moment the event started (from the date string)
  49. if (typeof(YYYY) === "string") {
  50. //in case there was a decimal place
  51. start = YYYY.split(".");
  52. ms = start[1] ? +("0." + start[1]) * 1000 : undefined;
  53. YYYY = start[0];
  54. start = new Date(YYYY);
  55. if (ms) {
  56. start.setMilliseconds(ms);
  57. }
  58. } else {
  59. //in case a variable is undefined
  60. MM = MM ? MM : "01";
  61. DD = DD ? DD : "01";
  62. hh = hh ? hh : "00";
  63. mm = mm ? mm : "00";
  64. ss = ss ? ss : "00";
  65. //firefox doesn't recognize 2009-6-6 but does recognize 2009/6/6. Weird.
  66. date = [YYYY, MM, DD].join("/") + " " + [hh, mm, ss].join(":");
  67. start = YYYY ? new Date(date) : new Date(); //starts a counter if YYYY is undefined
  68. if (ms) {
  69. start.setMilliseconds(ms);
  70. }
  71. }
  72. this.p = properties(start);
  73. //the infamous Counter class.
  74. Counter = function Counter(rounded, conversions) {
  75. function update() {
  76. var now, today, a, b, dt, pl = 100;
  77. now = new Date();
  78. today = round(now);
  79. a = now > start ? start : now;
  80. b = now > start ? now : start;
  81. a = properties(rounded ? round(a) : a);
  82. b = properties(rounded ? round(b) : b);
  83. dt = b.d - a.d;
  84. if (conversions) {
  85. if (rounded) {
  86. pl = 1;
  87. }
  88. ms = parseInt(pl * dt, 10) / pl;
  89. ss = parseInt(pl * (dt /= 1000), 10) / pl;
  90. mm = parseInt(pl * (dt /= 60), 10) / pl;
  91. hh = parseInt(pl * (dt /= 60), 10) / pl;
  92. DD = parseInt(pl * (dt /= 24), 10) / pl;
  93. ww = parseInt(pl * DD / 7, 10) / pl;
  94. MM = parseInt(pl * (dt /= (365.25 / 12)), 10) / pl;
  95. YYYY = parseInt(pl * (dt /= 12), 10) / pl;
  96. } else {
  97. YYYY = b.Y - a.Y;
  98. MM = b.M - a.M;
  99. DD = b.D - a.D;
  100. hh = b.h - a.h;
  101. mm = b.m - a.m;
  102. ss = b.s - a.s;
  103. ms = b.ms - a.ms;
  104. if (ms < 0) {
  105. ss -= 1;
  106. ms += 1000;
  107. }
  108. if (ss < 0) {
  109. mm -= 1;
  110. ss += 60;
  111. }
  112. if (mm < 0) {
  113. hh -= 1;
  114. mm += 60;
  115. }
  116. if (hh < 0) {
  117. DD -= 1;
  118. hh += 24;
  119. }
  120. if (DD < 0) {
  121. MM -= 1;
  122. DD += 30;
  123. }
  124. if (MM < 0) {
  125. YYYY -= 1;
  126. MM += 12;
  127. }
  128. ww = (YYYY * 365.25 / 7) + (MM * 365.25 / 7 / 12) + (DD / 7);
  129. ww = parseInt(ww, 10);
  130. }
  131. return {
  132. years : YYYY,
  133. months : MM,
  134. days : DD,
  135. hours : hh,
  136. minutes : mm,
  137. seconds : ss,
  138. milliseconds : ms,
  139. weeks : ww
  140. };
  141. }
  142. this.__defineGetter__("years", function years() {
  143. return update().years;
  144. });
  145. this.__defineGetter__("months", function months() {
  146. return update().months;
  147. });
  148. this.__defineGetter__("days", function days() {
  149. return update().days;
  150. });
  151. this.__defineGetter__("hours", function hours() {
  152. return update().hours;
  153. });
  154. this.__defineGetter__("minutes", function minutes() {
  155. return update().minutes;
  156. });
  157. this.__defineGetter__("seconds", function seconds() {
  158. return update().seconds;
  159. });
  160. this.__defineGetter__("milliseconds", function milliseconds() {
  161. return update().milliseconds;
  162. });
  163. this.__defineGetter__("weeks", function weeks() {
  164. return update().weeks;
  165. });
  166. this.__defineGetter__("status", function status() {
  167. var i, r = [], u;
  168. u = "years months days weeks hours minutes seconds milliseconds".split(" ");
  169. for (i in u) {
  170. if (this.hasOwnProperty(u[i]) && this[u[i]]) {
  171. if (u[i] === "weeks") {
  172. r.push("(" + this[u[i]] + " " + u[i] + ")");
  173. } else {
  174. r.push(this[u[i]] + " " + u[i]);
  175. }
  176. }
  177. }
  178. return r.join(",\n");
  179. });
  180. this.fireworks = function fireworks() {
  181. var s = this.status;
  182. s = s.replace(/\n/g, " ");
  183. s = s.replace(/ /g, "%20");
  184. s = s.replace(/,%20\(.+/g, "");
  185. //Thanks Kenneth Kufluk
  186. //return "http://js-fireworks.appspot.com/?msg=" + s; //for debugging
  187. window.location.href = "http://js-fireworks.appspot.com/?msg=" + s;
  188. };
  189. };
  190. this.exactly.howMany = new Counter(0);
  191. this.exactly.conversions = new Counter(0, 1);
  192. this.rounded.howMany = new Counter(1);
  193. this.rounded.conversions = new Counter(1, 1);
  194. };
  195.  
  196. /* Usage:
  197.  * Every Timer has three sub-objects: 'p', 'exactly' and 'rounded'
  198.  * the 'p' object has the following properties:
  199.  * Y, M, D, h, m, s, ms, d, t
  200.  * The last two are for the original date object and it's time-equivalent.
  201.  * Y is short-hand for yourTimer.d.getFullYear(); the rest is self-explanatory.
  202.  *
  203.  * 'exactly' and 'rounded' are objects with the following properties:
  204.  * years, months, days, weeks, hours, minutes, seconds, milliseconds, status
  205.  * 'status' displays a pre-formatted status message.
  206.  */
  207.  
  208. /* Example with comments:
  209.  var asd, jkl, qwe, uio;
  210.  asd = new Timer(); //starts counting from 'now'.
  211.  jkl = new Timer("2010/2/8 13:56:11.9966"); //moment I finished this file
  212.  jkl.exactly.howMany.status //2 days, 21 hours, 37 minutes, ...
  213.  jkl.exactly.conversions.status; //0.09 months, 2.9 days, (0.41 weeks), ...
  214.  jkl.rounded.howMany.status; //3 days
  215.  jkl.rounded.conversions.status; //3 days, 72 hours, 4320 minutes, ...
  216.  uio = new Timer(2012, 12, 12, 12, 12, 12, 12); //end of the world!
  217.  uio.rounded.howMany.fireworks(); //takes you to some very nice fireworks
  218.  */

Report this snippet  

Comments

RSS Icon Subscribe to comments
Posted By: alvincrespo on February 12, 2010

Hey, thanks for the snippet. Any examples that you might have online?

Posted By: rolandog on February 13, 2010

No problem, I currently use it in this post

I set those as bookmarklets so that my fiancée knows how many days remain until our wedding.

I've set up another use by passing a query on the timer-js page (copy link, because it will automatically redirect you to the fireworks) in my blog. The c parameter is for the conversions...

If you have a browser with a JavaScript console, try copying and pasting some of the lines at the bottom of this snippet.

You need to login to post a comment.