Source: lib/time.js

  1. // Copyright (c) 2018 Intel Corporation. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. 'use strict';
  15. const rclnodejs = require('bindings')('rclnodejs');
  16. const Duration = require('./duration.js');
  17. const ClockType = require('./clock_type.js');
  18. const int64 = require('int64-napi');
  19. /**
  20. * @class - Class representing a Time in ROS
  21. */
  22. class Time {
  23. /**
  24. * Create a Time.
  25. * @param {number|string} [seconds=0] - The second part of the time.
  26. * @param {number|string} [nanoseconds=0] - The nanosecond part of the time.
  27. * @param {ClockType} [clockType=Clock.ClockType.SYSTEM_TIME] - The clock type.
  28. */
  29. constructor(seconds = 0, nanoseconds = 0, clockType = ClockType.SYSTEM_TIME) {
  30. if (typeof seconds !== 'number' && typeof seconds !== 'string') {
  31. throw new TypeError('Invalid argument of seconds');
  32. }
  33. if (typeof nanoseconds !== 'number' && typeof nanoseconds !== 'string') {
  34. throw new TypeError('Invalid argument of nanoseconds');
  35. }
  36. if (typeof clockType !== 'number') {
  37. throw new TypeError('Invalid argument of clockType');
  38. }
  39. if (
  40. int64.lt(seconds, 0) ||
  41. (typeof seconds === 'string' && seconds.startsWith('-'))
  42. ) {
  43. throw new RangeError('seconds value must not be negative');
  44. }
  45. if (
  46. int64.lt(nanoseconds, 0) ||
  47. (typeof nanoseconds === 'string' && nanoseconds.startsWith('-'))
  48. ) {
  49. throw new RangeError('nanoseconds value must not be negative');
  50. }
  51. this._nanoseconds = int64.from(seconds).multiply(1e9).add(nanoseconds);
  52. this._handle = rclnodejs.createTimePoint(
  53. this._nanoseconds.toString(),
  54. clockType
  55. );
  56. this._clockType = clockType;
  57. }
  58. /**
  59. * Get the the clock type of the Time object.
  60. * @name Time#get:clockType
  61. * @function
  62. * @return {ClockType} - The clock type.
  63. */
  64. get clockType() {
  65. return this._clockType;
  66. }
  67. /**
  68. * Get the nanosecond part of the time.
  69. * @name Time#get:nanoseconds
  70. * @function
  71. * @return {number|string} - value in nanosecond, if the value is greater than Number.MAX_SAFE_INTEGER (2^53-1), will be presented in string of decimal format.
  72. */
  73. get nanoseconds() {
  74. let str = rclnodejs.getNanoseconds(this._handle);
  75. let nano;
  76. if (str.startsWith('-')) {
  77. nano = int64.negative(int64.from(str));
  78. } else {
  79. nano = int64.from(str);
  80. }
  81. if (Number.isFinite(nano.toNumber())) {
  82. return nano.toNumber();
  83. }
  84. return nano.toString();
  85. }
  86. /**
  87. * Get the time as separate seconds and nanoseconds component.
  88. * @name Time#get:secondsAndNanoseconds
  89. * @function
  90. * @return {object} - object with properties seconds and nanoseconds.
  91. */
  92. get secondsAndNanoseconds() {
  93. const seconds = int64.from(this._nanoseconds).divide(1e9).toNumber();
  94. const nanoseconds = int64.from(this._nanoseconds).mod(1e9).toNumber();
  95. return { seconds, nanoseconds };
  96. }
  97. /**
  98. * Add a duration to this time object.
  99. * @param {Duration} other - The Duration object to be added.
  100. * @return {Time} Return the result of a new Time object.
  101. */
  102. add(other) {
  103. if (other instanceof Duration) {
  104. return new Time(
  105. 0,
  106. int64.add(this._nanoseconds, other.nanoseconds).toString(),
  107. this._clockType
  108. );
  109. }
  110. throw new TypeError('Invalid argument');
  111. }
  112. /**
  113. * Subtract a duration/time to this time object.
  114. * @param {Duration|Time} other - The time to be subtracted.
  115. * @return {Duration|Time} Return the result.
  116. */
  117. sub(other) {
  118. if (other instanceof Time) {
  119. if (other._clockType !== this._clockType) {
  120. throw new TypeError("Can't subtract times with different clock types");
  121. }
  122. return new Duration(
  123. 0,
  124. int64.subtract(this._nanoseconds, other._nanoseconds).toString()
  125. );
  126. } else if (other instanceof Duration) {
  127. return new Time(
  128. 0,
  129. int64.subtract(this._nanoseconds, other._nanoseconds).toString(),
  130. this._clockType
  131. );
  132. }
  133. throw new TypeError('Invalid argument');
  134. }
  135. /**
  136. * Determine whether two Time objects are equal.
  137. * @param {Time} other - The time object to be compared.
  138. * @return {boolean} Return true if they are equal.
  139. */
  140. eq(other) {
  141. if (other instanceof Time) {
  142. if (other._clockType !== this._clockType) {
  143. throw new TypeError("Can't compare times with different clock types");
  144. }
  145. return this._nanoseconds.eq(other.nanoseconds);
  146. }
  147. throw new TypeError('Invalid argument');
  148. }
  149. /**
  150. * Determine whether two Time objects are not equal.
  151. * @param {Time} other - The time object to be compared.
  152. * @return {boolean} Return true if they are not equal.
  153. */
  154. ne(other) {
  155. if (other instanceof Time) {
  156. if (other._clockType !== this._clockType) {
  157. throw new TypeError("Can't compare times with different clock types");
  158. }
  159. return this._nanoseconds.ne(other.nanoseconds);
  160. }
  161. }
  162. /**
  163. * Determine whether the time is less than another one.
  164. * @param {Time} other - The time object to be compared.
  165. * @return {boolean} Return true if it's less than other.
  166. */
  167. lt(other) {
  168. if (other instanceof Time) {
  169. if (other._clockType !== this._clockType) {
  170. throw new TypeError("Can't compare times with different clock types");
  171. }
  172. return this._nanoseconds.lt(other.nanoseconds);
  173. }
  174. throw new TypeError('Invalid argument');
  175. }
  176. /**
  177. * Determine whether the time is less than or equal with another one.
  178. * @param {Time} other - The time object to be compared.
  179. * @return {boolean} Return true if it's less than or equal with other.
  180. */
  181. lte(other) {
  182. if (other instanceof Time) {
  183. if (other._clockType !== this._clockType) {
  184. throw new TypeError("Can't compare times with different clock types");
  185. }
  186. return this._nanoseconds.lte(other.nanoseconds);
  187. }
  188. throw new TypeError('Invalid argument');
  189. }
  190. /**
  191. * Determine whether the time is greater than another one.
  192. * @param {Time} other - The time object to be compared.
  193. * @return {boolean} Return true if it's greater than other.
  194. */
  195. gt(other) {
  196. if (other instanceof Time) {
  197. if (other._clockType !== this._clockType) {
  198. throw new TypeError("Can't compare times with different clock types");
  199. }
  200. return this._nanoseconds.gt(other.nanoseconds);
  201. }
  202. throw new TypeError('Invalid argument');
  203. }
  204. /**
  205. * Determine whether the time is greater than or equal with another one.
  206. * @param {Time} other - The time object to be compared.
  207. * @return {boolean} Return true if it's greater than or equal with other.
  208. */
  209. gte(other) {
  210. if (other instanceof Time) {
  211. if (other._clockType !== this._clockType) {
  212. throw new TypeError("Can't compare times with different clock types");
  213. }
  214. return this._nanoseconds.gte(other.nanoseconds);
  215. }
  216. throw new TypeError('Invalid argument');
  217. }
  218. /**
  219. * Create a builtin_interfaces.msg.Time message
  220. *
  221. * @return {builtin_interfaces.msg.Time} - The new Time message.
  222. */
  223. toMsg() {
  224. const secondsAndNanoseconds = this.secondsAndNanoseconds;
  225. return {
  226. sec: secondsAndNanoseconds.seconds,
  227. nanosec: secondsAndNanoseconds.nanoseconds,
  228. };
  229. }
  230. /**
  231. * Create a Time object from a message of builtin_interfaces/msg/Time
  232. * @param {object} msg - The builtin_interfaces.msg.Time message to be
  233. * created from.
  234. * @param {ClockType} [clockType=Clock.ClockType.ROS_TIME] - The type of the time object.
  235. * @return {Time} Return the created Time object.
  236. */
  237. static fromMsg(msg, clockType = ClockType.ROS_TIME) {
  238. return new Time(msg.sec, msg.nanosec, clockType);
  239. }
  240. }
  241. module.exports = Time;