index.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. var moment = require('moment');
  2. /*
  3. TODO:
  4. http://en.wikipedia.org/wiki/ISO_week_date
  5. timezones / utc-mode
  6. rounding
  7. get span bounds
  8. fuzzy match unit names
  9. format
  10. maybe:
  11. arbitrary year/quarter beginning
  12. arbitrary beginning day of week
  13. moment-style math operators
  14. */
  15. var UnixTime = function(unit, date) {
  16. this.uts = moment(date).unix();
  17. this.unit = unit;
  18. this.qty = UnixTime.from(unit, date);
  19. }
  20. // takes a unix timestamp, returns quantity of selected unix-units
  21. var fromFns = {
  22. // these are the easy ones
  23. seconds: function(ts) { return ts },
  24. minutes: function(ts) { return Math.floor(ts / 60) }, // rounding?
  25. hours: function(ts) { return Math.floor(ts / 3600) }, // rounding?
  26. days: function(ts) { return Math.floor(ts / (3600*24)) }, // rounding?
  27. weeks: function(ts) { return Math.floor(ts / (3600*24*7)) }, // BUG: TODO: offset, the epoch was a thursday, rounding?
  28. // these are the hard ones: leap years and other length variation
  29. months: function(ts) {
  30. var m = moment.unix(ts);
  31. return (m.year() - 1970) * 12 + m.month();
  32. }, // rounding?
  33. quarters: function(ts) {
  34. var m = moment.unix(ts);
  35. return (m.year() - 1970) * 4 + m.quarter() - 1; // moment quarters are 1-based
  36. }, // rounding?
  37. // back to easy ones
  38. years: function(ts) { return moment.unix(ts).year() - 1970 },
  39. decades: function(ts) { return Math.floor((moment.unix(ts).year() - 1970) / 10) },
  40. scores: function(ts) { return Math.floor((moment.unix(ts).year() - 1970) / 20) },
  41. centuries: function(ts) { return Math.floor((moment.unix(ts).year() - 1970) / 100) },
  42. millenia: function(ts) { return Math.floor((moment.unix(ts).year() - 1970) / 1000) }, // why not?
  43. };
  44. // takes quantity of selected unix units, returns a moment
  45. var toFns = {
  46. // these are the easy ones
  47. seconds: function(uu) { return moment.unix(uu) },
  48. minutes: function(uu) { return moment.unix(uu * 60) }, // rounding?
  49. hours: function(uu) { return moment.unix(uu * 3600) }, // rounding?
  50. days: function(uu) { return moment.unix(uu * 3600*24) }, // rounding?
  51. weeks: function(uu) { return moment.unix(uu * 3600*24*7) }, // BUG: TODO: offset, the epoch was a thursday, rounding?
  52. // these are the hard ones: leap years and other length variation
  53. months: function(uu) { return moment.year(Math.floor(uu / 12) + 1970).month(uu % 12) }, // rounding?
  54. quarters: function(uu) { return moment.year(Math.floor(uu / 4) + 1970).quarter((uu % 4) + 1) }, // moment quarters are 1-based rounding?
  55. // back to easy ones
  56. years: function(uu) { return moment.year(uu + 1970) },
  57. decades: function(uu) { return moment.year(uu * 10 + 1970) },
  58. scores: function(uu) { return moment.year(uu * 20 + 1970) },
  59. centuries: function(uu) { return moment.year(uu * 100 + 1970) },
  60. millenia: function(uu) { return moment.year(uu * 1000 + 1970) }, // why not?
  61. };
  62. UnixTime.prototype.valueOf = function() {
  63. return this.qty;
  64. };
  65. UnixTime.prototype.timestamp = function() {
  66. return this.uts;
  67. };
  68. // returns a moment for the beginning of a given unix-unit quantity
  69. // kind of a crap implementation.
  70. UnixTime.prototype.toMoment = function() {
  71. if(!toFns[this.unit]) return null;
  72. return toFns[this.unit](this.qty);
  73. };
  74. // returns the unix-unit quantity for the beginning span a given moment falls in
  75. // kind of a crap implementation.
  76. UnixTime.prototype.from = UnixTime.prototype.parse = function(unit, date) {
  77. if(!fromFns[unit]) return null; // TODO: need nice error handling and fuzzy matching here
  78. this.unit = unit;
  79. this.qty = fromFns[unit](moment(date).unix());
  80. return this;
  81. };
  82. // returns moments for the start and end points of a given unix-unit
  83. // in a way this is the inverse function of UnixTime.from
  84. UnixTime.boundingSpan = function(unit, qty) {
  85. return [
  86. this.toMoment(unit, qty),
  87. UnixTime.toMoment(unit, qty+1) //BUG: broken from refactoring
  88. ]
  89. };
  90. // passthrough of moment.format
  91. UnixTime.prototype.format = function(fmtStr) {
  92. var m = UnixTime.toMoment(this.unit, this.qty);
  93. if(!m) return m;
  94. return m.format(fmtStr);
  95. };
  96. // fancy string like "34th week of 1977" or "October 1993"
  97. UnixTime.prototype.desc = function() {
  98. var m = this.toMoment();
  99. switch(this.unit) {
  100. case 'seconds':
  101. return m.format('YYYY-MM-DD HH:mm:ss'); // check up on the format
  102. case 'minutes':
  103. return m.format('YYYY-MM-DD HH:mm'); // check up on the format
  104. case 'hours':
  105. return m.format('YYYY-MM-DD HH:mm'); // check up on the format
  106. case 'days':
  107. return m.format('YYYY-MM-DD'); // check up on the format
  108. case 'weeks':
  109. return m.format('wo week of YYYY'); // check up on the format
  110. case 'months':
  111. return m.format('MMMM YYYY'); // check up on the format
  112. case 'quarters':
  113. var q = ['1st', '2nd', '3rd', '4th'][m.quarter() - 1];
  114. return m.format(q + ' quarter YYYY'); // check up on the format
  115. case 'years':
  116. return m.format('YYYY'); // check up on the format
  117. case 'decades':
  118. return m.year((m.year()/10)|0*10).format('YYYY') + "'s"; // check up on the format
  119. case 'scores':
  120. return m.year((m.year()/10)|0*10).format('YYYY') + "'s"; // check up on the format
  121. case 'centuries':
  122. return m.year((m.year()/10)|0*10).format('YYYY') + " century"; // check up on the format
  123. }
  124. // maybe there sould be a default init options
  125. module.exports = UnixTime;