pax_global_header00006660000000000000000000000064137773605240014530gustar00rootroot0000000000000052 comment=6ea8bab38d13a6afbe456714136c9adfa0590f96 approximate-now-1.0.2/000077500000000000000000000000001377736052400146625ustar00rootroot00000000000000approximate-now-1.0.2/.editorconfig000066400000000000000000000002231377736052400173340ustar00rootroot00000000000000root = true [*] charset = utf-8 end_of_line = lf indent_size = 2 indent_style = space insert_final_newline = true trim_trailing_whitespace = true approximate-now-1.0.2/.eslintignore000066400000000000000000000000001377736052400173530ustar00rootroot00000000000000approximate-now-1.0.2/.eslintrc000066400000000000000000000002331377736052400165040ustar00rootroot00000000000000{ "extends": [ "canonical", "canonical/node", "canonical/typescript" ], "root": true, "rules": { "node/no-missing-import": 0 } } approximate-now-1.0.2/.github/000077500000000000000000000000001377736052400162225ustar00rootroot00000000000000approximate-now-1.0.2/.github/FUNDING.yml000066400000000000000000000000351377736052400200350ustar00rootroot00000000000000github: gajus patreon: gajus approximate-now-1.0.2/.gitignore000077500000000000000000000002541377736052400166560ustar00rootroot00000000000000coverage dist node_modules *.log .* !.editorconfig !.eslintignore !.eslintrc !.flowconfig !.github !.gitignore !.npmignore !.nycrc !.README !.travis.yml /package-lock.json approximate-now-1.0.2/.npmignore000066400000000000000000000000451377736052400166600ustar00rootroot00000000000000src test coverage benchmark .* *.log approximate-now-1.0.2/.nycrc000066400000000000000000000001041377736052400157740ustar00rootroot00000000000000{ "extends": "@istanbuljs/nyc-config-typescript", "all": true } approximate-now-1.0.2/.travis.yml000066400000000000000000000004711377736052400167750ustar00rootroot00000000000000language: node_js node_js: - node - 10 script: - npm run lint - npm run test - nyc --silent npm run test - nyc report --reporter=text-lcov | coveralls - nyc check-coverage --lines 80 after_success: - NODE_ENV=production npm run build - semantic-release notifications: email: false sudo: false approximate-now-1.0.2/LICENSE000066400000000000000000000027711377736052400156760ustar00rootroot00000000000000Copyright (c) 2020, Gajus Kuizinas (http://gajus.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. approximate-now-1.0.2/README.md000066400000000000000000000047141377736052400161470ustar00rootroot00000000000000# approximate-now [![Travis build status](http://img.shields.io/travis/gajus/approximate-now/master.svg?style=flat-square)](https://travis-ci.org/gajus/approximate-now) [![Coveralls](https://img.shields.io/coveralls/gajus/approximate-now.svg?style=flat-square)](https://coveralls.io/github/gajus/approximate-now) [![NPM version](http://img.shields.io/npm/v/approximate-now.svg?style=flat-square)](https://www.npmjs.org/package/approximate-now) [![Canonical Code Style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical) [![Twitter Follow](https://img.shields.io/twitter/follow/kuizinas.svg?style=social&label=Follow)](https://twitter.com/kuizinas) Approximate (fast) current UNIX time. ## Motivation Sometimes you don't care about the exact time the event took place, but rather need to know approximately when. If your use case is performance sensitive, then `Date.now()` might not be the best option because it has a [measurable impact](#benchmark) to the performance. `approximate-now` provides an approximate (to the error of 50ms) time without a performance penalty of `Date.now()`. ## Usage ```js import { approximateTime, } from 'approximate-now'; // `approximateTime.now` value is updated by reference every 50ms. console.log(approximateTime.now); ``` ## Sequence guarantee It is guaranteed that two consequent attempts to retrieve time within the same 50ms time window will have unique values, i.e. Assuming that the current time is `0000000000000`, then: ```js approximateTime.now; // 0000000000000 approximateTime.now; // 0000000000001 approximateTime.now; // 0000000000002 ``` However, if `approximateTime.now` is accessed more than 50 times within the same 50ms time window, then the top-most value within that interval is returned repeatedly. ```js approximateTime.now; // 0000000000000 approximateTime.now; // 0000000000001 approximateTime.now; // 0000000000002 // approximateTime.now x 50 approximateTime.now; // 0000000000050 approximateTime.now; // 0000000000050 approximateTime.now; // 0000000000050 ``` ## benchmark ``` Date.now() x 19,900,411 ops/sec ±0.59% (93 runs sampled) approximateTime.now x 82,420,291 ops/sec ±0.83% (92 runs sampled) ``` ## Use cases Any sort of time-sensitive operations when it is sufficient to retrieve an approximate timestamp, e.g. [`roarr`](https://github.com/gajus/roarr) logger uses `approximate-now` to record the time when a log message was produced. approximate-now-1.0.2/package.json000066400000000000000000000030171377736052400171510ustar00rootroot00000000000000{ "author": { "email": "gajus@gajus.com", "name": "Gajus Kuizinas", "url": "http://gajus.com" }, "ava": { "extensions": [ "ts" ], "files": [ "test/approximate-now/**/*" ], "require": [ "ts-node/register/transpile-only" ] }, "description": "Approximate (fast) current UNIX time.", "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "ava": "^3.14.0", "benchmark": "^2.1.4", "coveralls": "^3.1.0", "del-cli": "^3.0.1", "delay": "^4.4.0", "eslint": "^7.16.0", "eslint-config-canonical": "^24.4.4", "husky": "^4.3.6", "nyc": "^15.1.0", "semantic-release": "^17.3.0", "ts-node": "^9.1.1", "typescript": "^4.1.3" }, "engines": { "node": ">=10.0" }, "husky": { "hooks": { "pre-commit": "npm run lint && npm run test && npm run build" } }, "keywords": [ "log", "logger", "json" ], "license": "BSD-3-Clause", "main": "./dist/approximateNow.js", "name": "approximate-now", "repository": { "type": "git", "url": "git@github.com:gajus/approximate-now.git" }, "scripts": { "benchmark": "ROARR_LOG=true ts-node --transpile-only test/benchmark.ts", "build": "del-cli ./dist && tsc", "create-readme": "gitdown ./.README/README.md --output-file ./README.md", "dev": "tsc --watch", "lint": "eslint ./src ./test && tsc --noEmit", "test": "NODE_ENV=test ava --serial --verbose" }, "typings": "./dist/approximateNow.d.ts", "version": "1.0.0" } approximate-now-1.0.2/src/000077500000000000000000000000001377736052400154515ustar00rootroot00000000000000approximate-now-1.0.2/src/approximateNow.ts000066400000000000000000000011231377736052400210330ustar00rootroot00000000000000let now = 50 * Math.ceil(Date.now() / 50); let maxNow = 50 * Math.ceil((now + 50) / 50); const approximateTime = { now, }; Object.defineProperty( approximateTime, 'now', { get: () => { if (now < maxNow) { return now++; } return maxNow; }, set: (nextNow) => { now = nextNow; maxNow = 50 * Math.ceil((now + 50) / 50); }, }, ); const interval = setInterval( () => { approximateTime.now = 50 * Math.ceil(Date.now() / 50); }, 50, ); if (interval && interval.unref) { interval.unref(); } export { approximateTime, }; approximate-now-1.0.2/test/000077500000000000000000000000001377736052400156415ustar00rootroot00000000000000approximate-now-1.0.2/test/.eslintrc000066400000000000000000000001461377736052400174660ustar00rootroot00000000000000{ "extends": "canonical/ava", "rules": { "filenames/match-regex": 0, "id-length": 0 } } approximate-now-1.0.2/test/approximate-now/000077500000000000000000000000001377736052400207735ustar00rootroot00000000000000approximate-now-1.0.2/test/approximate-now/approximateNow.ts000066400000000000000000000045051377736052400243640ustar00rootroot00000000000000/* eslint-disable no-unused-expressions */ /* eslint-disable fp/no-delete */ import test from 'ava'; import delay from 'delay'; import { approximateTime, } from '../../src/approximateNow'; test('updates every 50ms', async (t) => { const firstTime = approximateTime.now; await delay(100); t.true(firstTime < approximateTime.now); }); test('increments time after every measurement', (t) => { t.not(approximateTime.now, approximateTime.now); }); test('does not increment beyond 50', (t) => { const times = []; times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); times.push(approximateTime.now); t.is(times[times.length - 1], times[times.length - 2]); }); approximate-now-1.0.2/test/benchmark.ts000066400000000000000000000011001377736052400201330ustar00rootroot00000000000000/* eslint-disable no-console */ import { Suite, } from 'benchmark'; import { approximateTime, } from '../src/approximateNow'; (() => { const suite = new Suite('roarr', { onCycle: (event) => { console.log(String(event.target)); }, onError: (event) => { console.error(event.target.error); }, }); suite.add( 'Date.now()', () => { Date.now(); }, ); suite.add( 'approximateTime.now', () => { // eslint-disable-next-line no-unused-expressions approximateTime.now; }, ); suite.run(); })(); approximate-now-1.0.2/tsconfig.json000066400000000000000000000010001377736052400173600ustar00rootroot00000000000000{ "compilerOptions": { "allowSyntheticDefaultImports": true, "declaration": true, "esModuleInterop": true, "lib": [ "es2020" ], "module": "commonjs", "moduleResolution": "node", "noImplicitAny": false, "noImplicitReturns": true, "noUnusedLocals": true, "noUnusedParameters": false, "outDir": "dist", "skipLibCheck": true, "strict": true, "target": "es2020" }, "exclude": [ "dist", "node_modules" ], "include": [ "src" ] }