TelemetryUtils.jsm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. this.EXPORTED_SYMBOLS = [
  6. "TelemetryUtils"
  7. ];
  8. const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
  9. Cu.import("resource://gre/modules/Preferences.jsm", this);
  10. const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
  11. const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
  12. const IS_CONTENT_PROCESS = (function() {
  13. // We cannot use Services.appinfo here because in telemetry xpcshell tests,
  14. // appinfo is initially unavailable, and becomes available only later on.
  15. let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
  16. return runtime.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
  17. })();
  18. this.TelemetryUtils = {
  19. /**
  20. * True if this is a content process.
  21. */
  22. get isContentProcess() {
  23. return IS_CONTENT_PROCESS;
  24. },
  25. /**
  26. * Returns the state of the Telemetry enabled preference, making sure
  27. * it correctly evaluates to a boolean type.
  28. */
  29. get isTelemetryEnabled() {
  30. return Preferences.get(PREF_TELEMETRY_ENABLED, false) === true;
  31. },
  32. /**
  33. * Turn a millisecond timestamp into a day timestamp.
  34. *
  35. * @param aMsec A number of milliseconds since Unix epoch.
  36. * @return The number of whole days since Unix epoch.
  37. */
  38. millisecondsToDays: function(aMsec) {
  39. return Math.floor(aMsec / MILLISECONDS_PER_DAY);
  40. },
  41. /**
  42. * Takes a date and returns it trunctated to a date with daily precision.
  43. */
  44. truncateToDays: function(date) {
  45. return new Date(date.getFullYear(),
  46. date.getMonth(),
  47. date.getDate(),
  48. 0, 0, 0, 0);
  49. },
  50. /**
  51. * Check if the difference between the times is within the provided tolerance.
  52. * @param {Number} t1 A time in milliseconds.
  53. * @param {Number} t2 A time in milliseconds.
  54. * @param {Number} tolerance The tolerance, in milliseconds.
  55. * @return {Boolean} True if the absolute time difference is within the tolerance, false
  56. * otherwise.
  57. */
  58. areTimesClose: function(t1, t2, tolerance) {
  59. return Math.abs(t1 - t2) <= tolerance;
  60. },
  61. /**
  62. * Get the next midnight for a date.
  63. * @param {Object} date The date object to check.
  64. * @return {Object} The Date object representing the next midnight.
  65. */
  66. getNextMidnight: function(date) {
  67. let nextMidnight = new Date(this.truncateToDays(date));
  68. nextMidnight.setDate(nextMidnight.getDate() + 1);
  69. return nextMidnight;
  70. },
  71. /**
  72. * Get the midnight which is closer to the provided date.
  73. * @param {Object} date The date object to check.
  74. * @param {Number} tolerance The tolerance within we find the closest midnight.
  75. * @return {Object} The Date object representing the closes midnight, or null if midnight
  76. * is not within the midnight tolerance.
  77. */
  78. getNearestMidnight: function(date, tolerance) {
  79. let lastMidnight = this.truncateToDays(date);
  80. if (this.areTimesClose(date.getTime(), lastMidnight.getTime(), tolerance)) {
  81. return lastMidnight;
  82. }
  83. const nextMidnightDate = this.getNextMidnight(date);
  84. if (this.areTimesClose(date.getTime(), nextMidnightDate.getTime(), tolerance)) {
  85. return nextMidnightDate;
  86. }
  87. return null;
  88. },
  89. generateUUID: function() {
  90. let str = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
  91. // strip {}
  92. return str.substring(1, str.length - 1);
  93. },
  94. /**
  95. * Find how many months passed between two dates.
  96. * @param {Object} aStartDate The starting date.
  97. * @param {Object} aEndDate The ending date.
  98. * @return {Integer} The number of months between the two dates.
  99. */
  100. getElapsedTimeInMonths: function(aStartDate, aEndDate) {
  101. return (aEndDate.getMonth() - aStartDate.getMonth())
  102. + 12 * (aEndDate.getFullYear() - aStartDate.getFullYear());
  103. },
  104. /**
  105. * Date.toISOString() gives us UTC times, this gives us local times in
  106. * the ISO date format. See http://www.w3.org/TR/NOTE-datetime
  107. * @param {Object} date The input date.
  108. * @return {String} The local time ISO string.
  109. */
  110. toLocalTimeISOString: function(date) {
  111. function padNumber(number, places) {
  112. number = number.toString();
  113. while (number.length < places) {
  114. number = "0" + number;
  115. }
  116. return number;
  117. }
  118. let sign = (n) => n >= 0 ? "+" : "-";
  119. // getTimezoneOffset counter-intuitively returns -60 for UTC+1.
  120. let tzOffset = - date.getTimezoneOffset();
  121. // YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
  122. return padNumber(date.getFullYear(), 4)
  123. + "-" + padNumber(date.getMonth() + 1, 2)
  124. + "-" + padNumber(date.getDate(), 2)
  125. + "T" + padNumber(date.getHours(), 2)
  126. + ":" + padNumber(date.getMinutes(), 2)
  127. + ":" + padNumber(date.getSeconds(), 2)
  128. + "." + date.getMilliseconds()
  129. + sign(tzOffset) + padNumber(Math.floor(Math.abs(tzOffset / 60)), 2)
  130. + ":" + padNumber(Math.abs(tzOffset % 60), 2);
  131. },
  132. };