Source: client/time-utils.js

  1. /*
  2. * Copyright 2023, TeamDev. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Redistribution and use in source and/or binary forms, with or without
  11. * modification, must retain the above copyright notice and the following
  12. * disclaimer.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  15. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  16. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  18. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  20. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. "use strict";
  27. import {Timestamp} from '../proto/google/protobuf/timestamp_pb';
  28. /**
  29. * @typedef {Object} DurationValue
  30. *
  31. * @property {number} seconds
  32. * @property {number} minutes
  33. */
  34. const NANOSECONDS_IN_MILLISECOND = 1000;
  35. const MILLISECONDS_IN_SECOND = 1000;
  36. const SECONDS_IN_MINUTE = 60;
  37. const MILLISECONDS_IN_MINUTE = SECONDS_IN_MINUTE * MILLISECONDS_IN_SECOND;
  38. const MINUTES_IN_HOUR = 60;
  39. const SECONDS_IN_HOUR = MINUTES_IN_HOUR * SECONDS_IN_MINUTE;
  40. const MILLISECONDS_IN_HOUR = SECONDS_IN_HOUR * MILLISECONDS_IN_SECOND;
  41. const HOURS_IN_DAY = 24;
  42. const MINUTES_IN_DAY = MINUTES_IN_HOUR * HOURS_IN_DAY;
  43. const SECONDS_IN_DAY = MINUTES_IN_DAY * SECONDS_IN_MINUTE;
  44. const MILLISECONDS_IN_DAY = SECONDS_IN_DAY * MILLISECONDS_IN_SECOND;
  45. /**
  46. * Checks that each item in provided items is non-negative. An error is thrown otherwise.
  47. *
  48. * @param {!number[]} items an array of numbers to check
  49. * @param {!String} message a message for when one of the items does not match the requirement
  50. */
  51. function checkItemsNotNegative(items, message) {
  52. items.forEach(item => {
  53. if (item < 0) {
  54. throw new Error(message);
  55. }
  56. });
  57. }
  58. /**
  59. * Converts a given JavaScript Date into the Timestamp Protobuf message.
  60. *
  61. * @param {!Date} date a date to convert
  62. * @return {Timestamp} a timestamp message of the given date value
  63. *
  64. * @throws error when non-Date value is passed or it is invalid
  65. */
  66. export function convertDateToTimestamp(date) {
  67. const errorMessage = (message) => `Cannot convert to Timestamp. ${message}`;
  68. if (!(date instanceof Date && typeof date.getTime === 'function')) {
  69. throw new Error(errorMessage(`The given "${date}" isn't of Date type.`));
  70. }
  71. if (isNaN(date.getTime())) {
  72. throw new Error(errorMessage(`The given "${date}" is invalid.`));
  73. }
  74. const millis = date.getTime();
  75. const timestamp = new Timestamp();
  76. timestamp.setSeconds(Math.trunc(millis / 1000));
  77. timestamp.setNanos((millis % 1000) * 1000000);
  78. return timestamp;
  79. }
  80. /**
  81. * A duration of a specified amount of time.
  82. *
  83. * A duration can not be negative, throwing an error if any of the provided values are less than 0.
  84. */
  85. export class Duration {
  86. /**
  87. * @param {?number} nanoseconds a number of nanoseconds in addition to all other values
  88. * @param {?number} milliseconds a number of milliseconds in addition to all other values
  89. * @param {?number} seconds a number of seconds in addition to all other values
  90. * @param {?number} minutes a number of minutes in addition to all other values
  91. * @param {?number} hours a number of hours in addition to all other values
  92. * @param {?number} days a number of days in addition to all other values
  93. */
  94. constructor({nanoseconds, milliseconds, seconds, minutes, hours, days}) {
  95. checkItemsNotNegative(
  96. [nanoseconds, milliseconds, seconds, minutes, hours, days],
  97. 'Duration cannot be negative'
  98. );
  99. this._nanoseconds = nanoseconds;
  100. this._milliseconds = milliseconds;
  101. this._seconds = seconds;
  102. this._minutes = minutes;
  103. this._hours = hours;
  104. this._days = days;
  105. }
  106. /**
  107. * @return {DurationValue} a value provided to the `Duration` constructor
  108. */
  109. value() {
  110. return {
  111. nanoseconds: this._nanoseconds,
  112. milliseconds: this._milliseconds,
  113. seconds: this._seconds,
  114. minutes: this._minutes,
  115. hours: this._hours,
  116. days: this._days,
  117. };
  118. }
  119. /**
  120. * @return {number} a total number of ms of this Duration value amounts as an integer
  121. */
  122. inMs() {
  123. let total = 0;
  124. if (this._nanoseconds) {
  125. total += this._nanoseconds / NANOSECONDS_IN_MILLISECOND;
  126. }
  127. if (this._milliseconds) {
  128. total += this._milliseconds;
  129. }
  130. if (this._seconds) {
  131. total += this._seconds * MILLISECONDS_IN_SECOND;
  132. }
  133. if (this._minutes) {
  134. total += this._minutes * MILLISECONDS_IN_MINUTE;
  135. }
  136. if (this._hours) {
  137. total += this._hours * MILLISECONDS_IN_HOUR;
  138. }
  139. if (this._days) {
  140. total += this._days * MILLISECONDS_IN_DAY;
  141. }
  142. return Math.floor(total);
  143. }
  144. }