timestamp.js 24 KB

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