Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

timestamp.js 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. // Licensed under the Apache License, Version 2.0 (the "License");
  2. // you may not use this file except in compliance with the License.
  3. // You may obtain a copy of the License at
  4. //
  5. // http://www.apache.org/licenses/LICENSE-2.0
  6. //
  7. // Unless required by applicable law or agreed to in writing, software
  8. // distributed under the License is distributed on an "AS IS" BASIS,
  9. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. // See the License for the specific language governing permissions and
  11. // limitations under the License.
  12. //
  13. // Copyright 2009 Google Inc. All Rights Reserved
  14. /**
  15. * This type is for INTERNAL use in MongoDB only and should not be used in applications.
  16. * The appropriate corresponding type is the JavaScript Date type.
  17. *
  18. * Defines a Timestamp class for representing a 64-bit two's-complement
  19. * integer value, which faithfully simulates the behavior of a Java "Timestamp". This
  20. * implementation is derived from TimestampLib in GWT.
  21. *
  22. * Constructs a 64-bit two's-complement integer, given its low and high 32-bit
  23. * values as *signed* integers. See the from* functions below for more
  24. * convenient ways of constructing Timestamps.
  25. *
  26. * The internal representation of a Timestamp is the two given signed, 32-bit values.
  27. * We use 32-bit pieces because these are the size of integers on which
  28. * Javascript performs bit-operations. For operations like addition and
  29. * multiplication, we split each number into 16-bit pieces, which can easily be
  30. * multiplied within Javascript's floating-point representation without overflow
  31. * or change in sign.
  32. *
  33. * In the algorithms below, we frequently reduce the negative case to the
  34. * positive case by negating the input(s) and then post-processing the result.
  35. * Note that we must ALWAYS check specially whether those values are MIN_VALUE
  36. * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
  37. * a positive number, it overflows back into a negative). Not handling this
  38. * case would often result in infinite recursion.
  39. *
  40. * @class
  41. * @param {number} low the low (signed) 32 bits of the Timestamp.
  42. * @param {number} high the high (signed) 32 bits of the Timestamp.
  43. */
  44. function Timestamp(low, high) {
  45. if (!(this instanceof Timestamp)) return new Timestamp(low, high);
  46. this._bsontype = 'Timestamp';
  47. /**
  48. * @type {number}
  49. * @ignore
  50. */
  51. this.low_ = low | 0; // force into 32 signed bits.
  52. /**
  53. * @type {number}
  54. * @ignore
  55. */
  56. this.high_ = high | 0; // force into 32 signed bits.
  57. }
  58. /**
  59. * Return the int value.
  60. *
  61. * @return {number} the value, assuming it is a 32-bit integer.
  62. */
  63. Timestamp.prototype.toInt = function() {
  64. return this.low_;
  65. };
  66. /**
  67. * Return the Number value.
  68. *
  69. * @method
  70. * @return {number} the closest floating-point representation to this value.
  71. */
  72. Timestamp.prototype.toNumber = function() {
  73. return this.high_ * Timestamp.TWO_PWR_32_DBL_ + this.getLowBitsUnsigned();
  74. };
  75. /**
  76. * Return the JSON value.
  77. *
  78. * @method
  79. * @return {string} the JSON representation.
  80. */
  81. Timestamp.prototype.toJSON = function() {
  82. return this.toString();
  83. };
  84. /**
  85. * Return the String value.
  86. *
  87. * @method
  88. * @param {number} [opt_radix] the radix in which the text should be written.
  89. * @return {string} the textual representation of this value.
  90. */
  91. Timestamp.prototype.toString = function(opt_radix) {
  92. var radix = opt_radix || 10;
  93. if (radix < 2 || 36 < radix) {
  94. throw Error('radix out of range: ' + radix);
  95. }
  96. if (this.isZero()) {
  97. return '0';
  98. }
  99. if (this.isNegative()) {
  100. if (this.equals(Timestamp.MIN_VALUE)) {
  101. // We need to change the Timestamp value before it can be negated, so we remove
  102. // the bottom-most digit in this base and then recurse to do the rest.
  103. var radixTimestamp = Timestamp.fromNumber(radix);
  104. var div = this.div(radixTimestamp);
  105. var rem = div.multiply(radixTimestamp).subtract(this);
  106. return div.toString(radix) + rem.toInt().toString(radix);
  107. } else {
  108. return '-' + this.negate().toString(radix);
  109. }
  110. }
  111. // Do several (6) digits each time through the loop, so as to
  112. // minimize the calls to the very expensive emulated div.
  113. var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6));
  114. rem = this;
  115. var result = '';
  116. while (!rem.isZero()) {
  117. var remDiv = rem.div(radixToPower);
  118. var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
  119. var digits = intval.toString(radix);
  120. rem = remDiv;
  121. if (rem.isZero()) {
  122. return digits + result;
  123. } else {
  124. while (digits.length < 6) {
  125. digits = '0' + digits;
  126. }
  127. result = '' + digits + result;
  128. }
  129. }
  130. };
  131. /**
  132. * Return the high 32-bits value.
  133. *
  134. * @method
  135. * @return {number} the high 32-bits as a signed value.
  136. */
  137. Timestamp.prototype.getHighBits = function() {
  138. return this.high_;
  139. };
  140. /**
  141. * Return the low 32-bits value.
  142. *
  143. * @method
  144. * @return {number} the low 32-bits as a signed value.
  145. */
  146. Timestamp.prototype.getLowBits = function() {
  147. return this.low_;
  148. };
  149. /**
  150. * Return the low unsigned 32-bits value.
  151. *
  152. * @method
  153. * @return {number} the low 32-bits as an unsigned value.
  154. */
  155. Timestamp.prototype.getLowBitsUnsigned = function() {
  156. return this.low_ >= 0 ? this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_;
  157. };
  158. /**
  159. * Returns the number of bits needed to represent the absolute value of this Timestamp.
  160. *
  161. * @method
  162. * @return {number} Returns the number of bits needed to represent the absolute value of this Timestamp.
  163. */
  164. Timestamp.prototype.getNumBitsAbs = function() {
  165. if (this.isNegative()) {
  166. if (this.equals(Timestamp.MIN_VALUE)) {
  167. return 64;
  168. } else {
  169. return this.negate().getNumBitsAbs();
  170. }
  171. } else {
  172. var val = this.high_ !== 0 ? this.high_ : this.low_;
  173. for (var bit = 31; bit > 0; bit--) {
  174. if ((val & (1 << bit)) !== 0) {
  175. break;
  176. }
  177. }
  178. return this.high_ !== 0 ? bit + 33 : bit + 1;
  179. }
  180. };
  181. /**
  182. * Return whether this value is zero.
  183. *
  184. * @method
  185. * @return {boolean} whether this value is zero.
  186. */
  187. Timestamp.prototype.isZero = function() {
  188. return this.high_ === 0 && this.low_ === 0;
  189. };
  190. /**
  191. * Return whether this value is negative.
  192. *
  193. * @method
  194. * @return {boolean} whether this value is negative.
  195. */
  196. Timestamp.prototype.isNegative = function() {
  197. return this.high_ < 0;
  198. };
  199. /**
  200. * Return whether this value is odd.
  201. *
  202. * @method
  203. * @return {boolean} whether this value is odd.
  204. */
  205. Timestamp.prototype.isOdd = function() {
  206. return (this.low_ & 1) === 1;
  207. };
  208. /**
  209. * Return whether this Timestamp equals the other
  210. *
  211. * @method
  212. * @param {Timestamp} other Timestamp to compare against.
  213. * @return {boolean} whether this Timestamp equals the other
  214. */
  215. Timestamp.prototype.equals = function(other) {
  216. return this.high_ === other.high_ && this.low_ === other.low_;
  217. };
  218. /**
  219. * Return whether this Timestamp does not equal the other.
  220. *
  221. * @method
  222. * @param {Timestamp} other Timestamp to compare against.
  223. * @return {boolean} whether this Timestamp does not equal the other.
  224. */
  225. Timestamp.prototype.notEquals = function(other) {
  226. return this.high_ !== other.high_ || this.low_ !== other.low_;
  227. };
  228. /**
  229. * Return whether this Timestamp is less than the other.
  230. *
  231. * @method
  232. * @param {Timestamp} other Timestamp to compare against.
  233. * @return {boolean} whether this Timestamp is less than the other.
  234. */
  235. Timestamp.prototype.lessThan = function(other) {
  236. return this.compare(other) < 0;
  237. };
  238. /**
  239. * Return whether this Timestamp is less than or equal to the other.
  240. *
  241. * @method
  242. * @param {Timestamp} other Timestamp to compare against.
  243. * @return {boolean} whether this Timestamp is less than or equal to the other.
  244. */
  245. Timestamp.prototype.lessThanOrEqual = function(other) {
  246. return this.compare(other) <= 0;
  247. };
  248. /**
  249. * Return whether this Timestamp is greater than the other.
  250. *
  251. * @method
  252. * @param {Timestamp} other Timestamp to compare against.
  253. * @return {boolean} whether this Timestamp is greater than the other.
  254. */
  255. Timestamp.prototype.greaterThan = function(other) {
  256. return this.compare(other) > 0;
  257. };
  258. /**
  259. * Return whether this Timestamp is greater than or equal to the other.
  260. *
  261. * @method
  262. * @param {Timestamp} other Timestamp to compare against.
  263. * @return {boolean} whether this Timestamp is greater than or equal to the other.
  264. */
  265. Timestamp.prototype.greaterThanOrEqual = function(other) {
  266. return this.compare(other) >= 0;
  267. };
  268. /**
  269. * Compares this Timestamp with the given one.
  270. *
  271. * @method
  272. * @param {Timestamp} other Timestamp to compare against.
  273. * @return {boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater.
  274. */
  275. Timestamp.prototype.compare = function(other) {
  276. if (this.equals(other)) {
  277. return 0;
  278. }
  279. var thisNeg = this.isNegative();
  280. var otherNeg = other.isNegative();
  281. if (thisNeg && !otherNeg) {
  282. return -1;
  283. }
  284. if (!thisNeg && otherNeg) {
  285. return 1;
  286. }
  287. // at this point, the signs are the same, so subtraction will not overflow
  288. if (this.subtract(other).isNegative()) {
  289. return -1;
  290. } else {
  291. return 1;
  292. }
  293. };
  294. /**
  295. * The negation of this value.
  296. *
  297. * @method
  298. * @return {Timestamp} the negation of this value.
  299. */
  300. Timestamp.prototype.negate = function() {
  301. if (this.equals(Timestamp.MIN_VALUE)) {
  302. return Timestamp.MIN_VALUE;
  303. } else {
  304. return this.not().add(Timestamp.ONE);
  305. }
  306. };
  307. /**
  308. * Returns the sum of this and the given Timestamp.
  309. *
  310. * @method
  311. * @param {Timestamp} other Timestamp to add to this one.
  312. * @return {Timestamp} the sum of this and the given Timestamp.
  313. */
  314. Timestamp.prototype.add = function(other) {
  315. // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
  316. var a48 = this.high_ >>> 16;
  317. var a32 = this.high_ & 0xffff;
  318. var a16 = this.low_ >>> 16;
  319. var a00 = this.low_ & 0xffff;
  320. var b48 = other.high_ >>> 16;
  321. var b32 = other.high_ & 0xffff;
  322. var b16 = other.low_ >>> 16;
  323. var b00 = other.low_ & 0xffff;
  324. var c48 = 0,
  325. c32 = 0,
  326. c16 = 0,
  327. c00 = 0;
  328. c00 += a00 + b00;
  329. c16 += c00 >>> 16;
  330. c00 &= 0xffff;
  331. c16 += a16 + b16;
  332. c32 += c16 >>> 16;
  333. c16 &= 0xffff;
  334. c32 += a32 + b32;
  335. c48 += c32 >>> 16;
  336. c32 &= 0xffff;
  337. c48 += a48 + b48;
  338. c48 &= 0xffff;
  339. return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
  340. };
  341. /**
  342. * Returns the difference of this and the given Timestamp.
  343. *
  344. * @method
  345. * @param {Timestamp} other Timestamp to subtract from this.
  346. * @return {Timestamp} the difference of this and the given Timestamp.
  347. */
  348. Timestamp.prototype.subtract = function(other) {
  349. return this.add(other.negate());
  350. };
  351. /**
  352. * Returns the product of this and the given Timestamp.
  353. *
  354. * @method
  355. * @param {Timestamp} other Timestamp to multiply with this.
  356. * @return {Timestamp} the product of this and the other.
  357. */
  358. Timestamp.prototype.multiply = function(other) {
  359. if (this.isZero()) {
  360. return Timestamp.ZERO;
  361. } else if (other.isZero()) {
  362. return Timestamp.ZERO;
  363. }
  364. if (this.equals(Timestamp.MIN_VALUE)) {
  365. return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO;
  366. } else if (other.equals(Timestamp.MIN_VALUE)) {
  367. return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO;
  368. }
  369. if (this.isNegative()) {
  370. if (other.isNegative()) {
  371. return this.negate().multiply(other.negate());
  372. } else {
  373. return this.negate()
  374. .multiply(other)
  375. .negate();
  376. }
  377. } else if (other.isNegative()) {
  378. return this.multiply(other.negate()).negate();
  379. }
  380. // If both Timestamps are small, use float multiplication
  381. if (this.lessThan(Timestamp.TWO_PWR_24_) && other.lessThan(Timestamp.TWO_PWR_24_)) {
  382. return Timestamp.fromNumber(this.toNumber() * other.toNumber());
  383. }
  384. // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products.
  385. // We can skip products that would overflow.
  386. var a48 = this.high_ >>> 16;
  387. var a32 = this.high_ & 0xffff;
  388. var a16 = this.low_ >>> 16;
  389. var a00 = this.low_ & 0xffff;
  390. var b48 = other.high_ >>> 16;
  391. var b32 = other.high_ & 0xffff;
  392. var b16 = other.low_ >>> 16;
  393. var b00 = other.low_ & 0xffff;
  394. var c48 = 0,
  395. c32 = 0,
  396. c16 = 0,
  397. c00 = 0;
  398. c00 += a00 * b00;
  399. c16 += c00 >>> 16;
  400. c00 &= 0xffff;
  401. c16 += a16 * b00;
  402. c32 += c16 >>> 16;
  403. c16 &= 0xffff;
  404. c16 += a00 * b16;
  405. c32 += c16 >>> 16;
  406. c16 &= 0xffff;
  407. c32 += a32 * b00;
  408. c48 += c32 >>> 16;
  409. c32 &= 0xffff;
  410. c32 += a16 * b16;
  411. c48 += c32 >>> 16;
  412. c32 &= 0xffff;
  413. c32 += a00 * b32;
  414. c48 += c32 >>> 16;
  415. c32 &= 0xffff;
  416. c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
  417. c48 &= 0xffff;
  418. return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
  419. };
  420. /**
  421. * Returns this Timestamp divided by the given one.
  422. *
  423. * @method
  424. * @param {Timestamp} other Timestamp by which to divide.
  425. * @return {Timestamp} this Timestamp divided by the given one.
  426. */
  427. Timestamp.prototype.div = function(other) {
  428. if (other.isZero()) {
  429. throw Error('division by zero');
  430. } else if (this.isZero()) {
  431. return Timestamp.ZERO;
  432. }
  433. if (this.equals(Timestamp.MIN_VALUE)) {
  434. if (other.equals(Timestamp.ONE) || other.equals(Timestamp.NEG_ONE)) {
  435. return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
  436. } else if (other.equals(Timestamp.MIN_VALUE)) {
  437. return Timestamp.ONE;
  438. } else {
  439. // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
  440. var halfThis = this.shiftRight(1);
  441. var approx = halfThis.div(other).shiftLeft(1);
  442. if (approx.equals(Timestamp.ZERO)) {
  443. return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE;
  444. } else {
  445. var rem = this.subtract(other.multiply(approx));
  446. var result = approx.add(rem.div(other));
  447. return result;
  448. }
  449. }
  450. } else if (other.equals(Timestamp.MIN_VALUE)) {
  451. return Timestamp.ZERO;
  452. }
  453. if (this.isNegative()) {
  454. if (other.isNegative()) {
  455. return this.negate().div(other.negate());
  456. } else {
  457. return this.negate()
  458. .div(other)
  459. .negate();
  460. }
  461. } else if (other.isNegative()) {
  462. return this.div(other.negate()).negate();
  463. }
  464. // Repeat the following until the remainder is less than other: find a
  465. // floating-point that approximates remainder / other *from below*, add this
  466. // into the result, and subtract it from the remainder. It is critical that
  467. // the approximate value is less than or equal to the real value so that the
  468. // remainder never becomes negative.
  469. var res = Timestamp.ZERO;
  470. rem = this;
  471. while (rem.greaterThanOrEqual(other)) {
  472. // Approximate the result of division. This may be a little greater or
  473. // smaller than the actual value.
  474. approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
  475. // We will tweak the approximate result by changing it in the 48-th digit or
  476. // the smallest non-fractional digit, whichever is larger.
  477. var log2 = Math.ceil(Math.log(approx) / Math.LN2);
  478. var delta = log2 <= 48 ? 1 : Math.pow(2, log2 - 48);
  479. // Decrease the approximation until it is smaller than the remainder. Note
  480. // that if it is too large, the product overflows and is negative.
  481. var approxRes = Timestamp.fromNumber(approx);
  482. var approxRem = approxRes.multiply(other);
  483. while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
  484. approx -= delta;
  485. approxRes = Timestamp.fromNumber(approx);
  486. approxRem = approxRes.multiply(other);
  487. }
  488. // We know the answer can't be zero... and actually, zero would cause
  489. // infinite recursion since we would make no progress.
  490. if (approxRes.isZero()) {
  491. approxRes = Timestamp.ONE;
  492. }
  493. res = res.add(approxRes);
  494. rem = rem.subtract(approxRem);
  495. }
  496. return res;
  497. };
  498. /**
  499. * Returns this Timestamp modulo the given one.
  500. *
  501. * @method
  502. * @param {Timestamp} other Timestamp by which to mod.
  503. * @return {Timestamp} this Timestamp modulo the given one.
  504. */
  505. Timestamp.prototype.modulo = function(other) {
  506. return this.subtract(this.div(other).multiply(other));
  507. };
  508. /**
  509. * The bitwise-NOT of this value.
  510. *
  511. * @method
  512. * @return {Timestamp} the bitwise-NOT of this value.
  513. */
  514. Timestamp.prototype.not = function() {
  515. return Timestamp.fromBits(~this.low_, ~this.high_);
  516. };
  517. /**
  518. * Returns the bitwise-AND of this Timestamp and the given one.
  519. *
  520. * @method
  521. * @param {Timestamp} other the Timestamp with which to AND.
  522. * @return {Timestamp} the bitwise-AND of this and the other.
  523. */
  524. Timestamp.prototype.and = function(other) {
  525. return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_);
  526. };
  527. /**
  528. * Returns the bitwise-OR of this Timestamp and the given one.
  529. *
  530. * @method
  531. * @param {Timestamp} other the Timestamp with which to OR.
  532. * @return {Timestamp} the bitwise-OR of this and the other.
  533. */
  534. Timestamp.prototype.or = function(other) {
  535. return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_);
  536. };
  537. /**
  538. * Returns the bitwise-XOR of this Timestamp and the given one.
  539. *
  540. * @method
  541. * @param {Timestamp} other the Timestamp with which to XOR.
  542. * @return {Timestamp} the bitwise-XOR of this and the other.
  543. */
  544. Timestamp.prototype.xor = function(other) {
  545. return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_);
  546. };
  547. /**
  548. * Returns this Timestamp with bits shifted to the left by the given amount.
  549. *
  550. * @method
  551. * @param {number} numBits the number of bits by which to shift.
  552. * @return {Timestamp} this shifted to the left by the given amount.
  553. */
  554. Timestamp.prototype.shiftLeft = function(numBits) {
  555. numBits &= 63;
  556. if (numBits === 0) {
  557. return this;
  558. } else {
  559. var low = this.low_;
  560. if (numBits < 32) {
  561. var high = this.high_;
  562. return Timestamp.fromBits(low << numBits, (high << numBits) | (low >>> (32 - numBits)));
  563. } else {
  564. return Timestamp.fromBits(0, low << (numBits - 32));
  565. }
  566. }
  567. };
  568. /**
  569. * Returns this Timestamp with bits shifted to the right by the given amount.
  570. *
  571. * @method
  572. * @param {number} numBits the number of bits by which to shift.
  573. * @return {Timestamp} this shifted to the right by the given amount.
  574. */
  575. Timestamp.prototype.shiftRight = function(numBits) {
  576. numBits &= 63;
  577. if (numBits === 0) {
  578. return this;
  579. } else {
  580. var high = this.high_;
  581. if (numBits < 32) {
  582. var low = this.low_;
  583. return Timestamp.fromBits((low >>> numBits) | (high << (32 - numBits)), high >> numBits);
  584. } else {
  585. return Timestamp.fromBits(high >> (numBits - 32), high >= 0 ? 0 : -1);
  586. }
  587. }
  588. };
  589. /**
  590. * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit.
  591. *
  592. * @method
  593. * @param {number} numBits the number of bits by which to shift.
  594. * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits.
  595. */
  596. Timestamp.prototype.shiftRightUnsigned = function(numBits) {
  597. numBits &= 63;
  598. if (numBits === 0) {
  599. return this;
  600. } else {
  601. var high = this.high_;
  602. if (numBits < 32) {
  603. var low = this.low_;
  604. return Timestamp.fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits);
  605. } else if (numBits === 32) {
  606. return Timestamp.fromBits(high, 0);
  607. } else {
  608. return Timestamp.fromBits(high >>> (numBits - 32), 0);
  609. }
  610. }
  611. };
  612. /**
  613. * Returns a Timestamp representing the given (32-bit) integer value.
  614. *
  615. * @method
  616. * @param {number} value the 32-bit integer in question.
  617. * @return {Timestamp} the corresponding Timestamp value.
  618. */
  619. Timestamp.fromInt = function(value) {
  620. if (-128 <= value && value < 128) {
  621. var cachedObj = Timestamp.INT_CACHE_[value];
  622. if (cachedObj) {
  623. return cachedObj;
  624. }
  625. }
  626. var obj = new Timestamp(value | 0, value < 0 ? -1 : 0);
  627. if (-128 <= value && value < 128) {
  628. Timestamp.INT_CACHE_[value] = obj;
  629. }
  630. return obj;
  631. };
  632. /**
  633. * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned.
  634. *
  635. * @method
  636. * @param {number} value the number in question.
  637. * @return {Timestamp} the corresponding Timestamp value.
  638. */
  639. Timestamp.fromNumber = function(value) {
  640. if (isNaN(value) || !isFinite(value)) {
  641. return Timestamp.ZERO;
  642. } else if (value <= -Timestamp.TWO_PWR_63_DBL_) {
  643. return Timestamp.MIN_VALUE;
  644. } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) {
  645. return Timestamp.MAX_VALUE;
  646. } else if (value < 0) {
  647. return Timestamp.fromNumber(-value).negate();
  648. } else {
  649. return new Timestamp(
  650. (value % Timestamp.TWO_PWR_32_DBL_) | 0,
  651. (value / Timestamp.TWO_PWR_32_DBL_) | 0
  652. );
  653. }
  654. };
  655. /**
  656. * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits.
  657. *
  658. * @method
  659. * @param {number} lowBits the low 32-bits.
  660. * @param {number} highBits the high 32-bits.
  661. * @return {Timestamp} the corresponding Timestamp value.
  662. */
  663. Timestamp.fromBits = function(lowBits, highBits) {
  664. return new Timestamp(lowBits, highBits);
  665. };
  666. /**
  667. * Returns a Timestamp representation of the given string, written using the given radix.
  668. *
  669. * @method
  670. * @param {string} str the textual representation of the Timestamp.
  671. * @param {number} opt_radix the radix in which the text is written.
  672. * @return {Timestamp} the corresponding Timestamp value.
  673. */
  674. Timestamp.fromString = function(str, opt_radix) {
  675. if (str.length === 0) {
  676. throw Error('number format error: empty string');
  677. }
  678. var radix = opt_radix || 10;
  679. if (radix < 2 || 36 < radix) {
  680. throw Error('radix out of range: ' + radix);
  681. }
  682. if (str.charAt(0) === '-') {
  683. return Timestamp.fromString(str.substring(1), radix).negate();
  684. } else if (str.indexOf('-') >= 0) {
  685. throw Error('number format error: interior "-" character: ' + str);
  686. }
  687. // Do several (8) digits each time through the loop, so as to
  688. // minimize the calls to the very expensive emulated div.
  689. var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8));
  690. var result = Timestamp.ZERO;
  691. for (var i = 0; i < str.length; i += 8) {
  692. var size = Math.min(8, str.length - i);
  693. var value = parseInt(str.substring(i, i + size), radix);
  694. if (size < 8) {
  695. var power = Timestamp.fromNumber(Math.pow(radix, size));
  696. result = result.multiply(power).add(Timestamp.fromNumber(value));
  697. } else {
  698. result = result.multiply(radixToPower);
  699. result = result.add(Timestamp.fromNumber(value));
  700. }
  701. }
  702. return result;
  703. };
  704. // NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
  705. // from* methods on which they depend.
  706. /**
  707. * A cache of the Timestamp representations of small integer values.
  708. * @type {Object}
  709. * @ignore
  710. */
  711. Timestamp.INT_CACHE_ = {};
  712. // NOTE: the compiler should inline these constant values below and then remove
  713. // these variables, so there should be no runtime penalty for these.
  714. /**
  715. * Number used repeated below in calculations. This must appear before the
  716. * first call to any from* function below.
  717. * @type {number}
  718. * @ignore
  719. */
  720. Timestamp.TWO_PWR_16_DBL_ = 1 << 16;
  721. /**
  722. * @type {number}
  723. * @ignore
  724. */
  725. Timestamp.TWO_PWR_24_DBL_ = 1 << 24;
  726. /**
  727. * @type {number}
  728. * @ignore
  729. */
  730. Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_;
  731. /**
  732. * @type {number}
  733. * @ignore
  734. */
  735. Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2;
  736. /**
  737. * @type {number}
  738. * @ignore
  739. */
  740. Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_;
  741. /**
  742. * @type {number}
  743. * @ignore
  744. */
  745. Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_;
  746. /**
  747. * @type {number}
  748. * @ignore
  749. */
  750. Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2;
  751. /** @type {Timestamp} */
  752. Timestamp.ZERO = Timestamp.fromInt(0);
  753. /** @type {Timestamp} */
  754. Timestamp.ONE = Timestamp.fromInt(1);
  755. /** @type {Timestamp} */
  756. Timestamp.NEG_ONE = Timestamp.fromInt(-1);
  757. /** @type {Timestamp} */
  758. Timestamp.MAX_VALUE = Timestamp.fromBits(0xffffffff | 0, 0x7fffffff | 0);
  759. /** @type {Timestamp} */
  760. Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0);
  761. /**
  762. * @type {Timestamp}
  763. * @ignore
  764. */
  765. Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24);
  766. /**
  767. * Expose.
  768. */
  769. module.exports = Timestamp;
  770. module.exports.Timestamp = Timestamp;