]> git.ipfire.org Git - thirdparty/moment.git/commitdiff
fix #5596: floating number calculation converter
authorAlanscut <wp_scut@163.com>
Sun, 14 Jun 2020 15:14:42 +0000 (23:14 +0800)
committerIskren Chernev <me@iskren.info>
Sat, 23 Dec 2023 18:43:26 +0000 (20:43 +0200)
src/lib/duration/constructor.js
src/lib/utils/float-calculate.js [new file with mode: 0644]
src/test/moment/duration.js

index 6033769b70336520ec90c7b61970e8777c82a9e9..ee8a94f5b733771a5202da68189aaf6c004b1369 100644 (file)
@@ -1,6 +1,7 @@
 import { normalizeObjectUnits } from '../units/aliases';
 import { getLocale } from '../locale/locales';
 import isDurationValid from './valid.js';
+import multiply from '../utils/float-calculate';
 
 export function Duration(duration) {
     var normalizedInput = normalizeObjectUnits(duration),
@@ -19,9 +20,9 @@ export function Duration(duration) {
     // representation for dateAddRemove
     this._milliseconds =
         +milliseconds +
-        seconds * 1e3 + // 1000
-        minutes * 6e4 + // 1000 * 60
-        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
+        multiply(seconds, 1e3) + // 1000
+        multiply(minutes, 6e4) + // 1000 * 60
+        multiply(hours, 36e5); //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
     // Because of dateAddRemove treats 24 hours as different from a
     // day when working around DST, we need to store them separately
     this._days = +days + weeks * 7;
diff --git a/src/lib/utils/float-calculate.js b/src/lib/utils/float-calculate.js
new file mode 100644 (file)
index 0000000..f7427e9
--- /dev/null
@@ -0,0 +1,33 @@
+export default function multiply(a, b) {
+    var bi1 = toBigInt(parseFloat(a)),
+        bi2 = toBigInt(parseFloat(b)),
+        mag1 = bi1.magnification,
+        mag2 = bi2.magnification,
+        num1 = bi1.num,
+        num2 = bi2.num;
+    return (num1 * num2) / (mag1 * mag2);
+}
+
+function toBigInt(floatNum) {
+    var bigInt = {
+            num: 0,
+            magnification: 1,
+        },
+        strNum,
+        len,
+        mag,
+        intNum;
+        
+    if (Math.floor(floatNum) === floatNum) {
+        bigInt.num = floatNum;
+        return bigInt;
+    }
+
+    strNum = floatNum.toString();
+    len = strNum.length - strNum.indexOf('.') - 1;
+    mag = Math.pow(10, len);
+    intNum = Number(floatNum.toString().replace('.', ''));
+    bigInt.num = intNum;
+    bigInt.magnification = mag;
+    return bigInt;
+}
index a1e97472bca79da1db96366c74c267400b503a2d..4d6c4898a3be3c7c14ba9b88a4ab90ba0bca04c1 100644 (file)
@@ -248,6 +248,13 @@ test('instantiation from another duration', function (assert) {
 });
 
 test('explicit cloning', function (assert) {
+    var duration = moment.duration(1.1234, 'hours');
+    assert.equal(duration.milliseconds(), 240,
+        'Float number calculation will not lose accuracy'
+    );
+});
+
+test('float number calculation', function (assert) {
     var durationA = moment.duration(5, 'milliseconds'),
         durationB = durationA.clone();
     durationA.add(5, 'milliseconds');