Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(parse-duration): add new package #36

Merged
merged 14 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .yarn/sdks/prettier/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "prettier",
"version": "3.1.1-sdk",
"version": "3.2.2-sdk",
"main": "./index.cjs",
"type": "commonjs",
"bin": "./bin/prettier.cjs"
Expand Down
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ This repository contains numerous small utility packages. These packages serve v

Here is a brief overview of the included libraries:

1. [`tsconfig-base`](./packages/tsconfig-base/README.md): This is a foundational TypeScript configuration used for Alwatr projects.
2. [`flat-string`](./packages/flat-string/README.md): The `flat-string` function flattens the underlying C structures of a concatenated JavaScript string.
3. [`global-scope`](./packages/global-scope/README.md): This TypeScript module provides a cross-platform alternative to `globalThis` named `globalScope`. This object works across different environments, including browsers (`window`), Node.js (`global`), and Web Workers (`self`).
4. [`platform-info`](./packages/platform-info/README.md): This module offers a method to identify the current platform where the script is being executed. It defines a `platformInfo` constant that contains details about the current platform.
5. [`prettier-config`](./packages/prettier-config/README.md): These are Alwatr's shared configurations for Prettier.
6. [`eslint-config`](./packages/eslint-config/README.md): This is Alwatr's ECMAScript Style Guide presented as shareable ESLint configurations.
7. [`deep-clone`](./packages/deep-clone/README.md): This function allows you to clone deeply nested objects and arrays in JavaScript.
8. [`nano-build`](./packages/nano-build/README.md): This is a tool for building/bundling ECMAScript, TypeScript, and JavaScript libraries. It's user-friendly, requires no setup, follows best practices, has no dependencies, and uses esbuild for improved performance.
9. [`type-helper`](./packages/type-helper/README.md): Collection of useful typescript type helpers.
10. [`wait`](./packages/wait/README.md): Comprehensive toolkit for managing asynchronous operations.
11. [`exit-hook`](./packages/exit-hook/README.md): A utility for registering exit handlers in Node.js.
12. [`flatomise`](./packages/flatomise/README.md): A utility for creating promises that can be externally resolved or rejected.
13. [`async-queue`](./packages/async-queue/README.md): A queue that executes async tasks in order like mutex and semaphore methodology for javascript and typescript.
14. [`node-fs`](./packages/node-fs/README.md): Enhanced file system operations in Node.js, including reading, writing, and handling JSON files, with both synchronous and asynchronous options.
15. [`is-number`](./packages/is-number/README.md): A simple utility to check if a value is a number.
1. [`tsconfig-base`](./packages/tsconfig-base#readme): This is a foundational TypeScript configuration used for Alwatr projects.
2. [`flat-string`](./packages/flat-string#readme): The `flat-string` function flattens the underlying C structures of a concatenated JavaScript string.
3. [`global-scope`](./packages/global-scope#readme): This TypeScript module provides a cross-platform alternative to `globalThis` named `globalScope`. This object works across different environments, including browsers (`window`), Node.js (`global`), and Web Workers (`self`).
4. [`platform-info`](./packages/platform-info#readme): This module offers a method to identify the current platform where the script is being executed. It defines a `platformInfo` constant that contains details about the current platform.
5. [`prettier-config`](./packages/prettier-config#readme): These are Alwatr's shared configurations for Prettier.
6. [`eslint-config`](./packages/eslint-config#readme): This is Alwatr's ECMAScript Style Guide presented as shareable ESLint configurations.
7. [`deep-clone`](./packages/deep-clone#readme): This function allows you to clone deeply nested objects and arrays in JavaScript.
8. [`nano-build`](./packages/nano-build#readme): This is a tool for building/bundling ECMAScript, TypeScript, and JavaScript libraries. It's user-friendly, requires no setup, follows best practices, has no dependencies, and uses esbuild for improved performance.
9. [`type-helper`](./packages/type-helper#readme): Collection of useful typescript type helpers.
10. [`wait`](./packages/wait#readme): Comprehensive toolkit for managing asynchronous operations.
11. [`exit-hook`](./packages/exit-hook#readme): A utility for registering exit handlers in Node.js.
12. [`flatomise`](./packages/flatomise#readme): A utility for creating promises that can be externally resolved or rejected.
13. [`async-queue`](./packages/async-queue#readme): A queue that executes async tasks in order like mutex and semaphore methodology for javascript and typescript.
14. [`node-fs`](./packages/node-fs#readme): Enhanced file system operations in Node.js, including reading, writing, and handling JSON files, with both synchronous and asynchronous options.
15. [`is-number`](./packages/is-number#readme): A simple utility to check if a value is a number.
16. [`parse-duration`](./packages/parse-duration#readme): A simple utility to parse a duration string into milliseconds number.

For more detailed information and guidelines on how to use each package, please refer to each package's README.
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@
"devDependencies": {
"@alwatr/eslint-config": "workspace:^",
"@alwatr/prettier-config": "workspace:^",
"@lerna-lite/changed": "^3.2.0",
"@lerna-lite/cli": "^3.2.0",
"@lerna-lite/diff": "^3.2.0",
"@lerna-lite/exec": "^3.2.0",
"@lerna-lite/publish": "^3.2.0",
"@lerna-lite/run": "^3.2.0",
"@lerna-lite/version": "^3.2.0",
"@typescript-eslint/eslint-plugin": "^6.18.1",
"@typescript-eslint/parser": "^6.18.1",
"@lerna-lite/changed": "^3.2.1",
"@lerna-lite/cli": "^3.2.1",
"@lerna-lite/diff": "^3.2.1",
"@lerna-lite/exec": "^3.2.1",
"@lerna-lite/publish": "^3.2.1",
"@lerna-lite/run": "^3.2.1",
"@lerna-lite/version": "^3.2.1",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"eslint": "^8.56.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"prettier": "^3.1.1",
"prettier": "^3.2.2",
"typescript": "^5.3.3"
},
"packageManager": "[email protected]"
Expand Down
2 changes: 1 addition & 1 deletion packages/async-queue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@alwatr/type-helper": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
2 changes: 1 addition & 1 deletion packages/dedupe/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@alwatr/type-helper": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
4 changes: 2 additions & 2 deletions packages/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
"devDependencies": {
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@typescript-eslint/eslint-plugin": "^6.18.1",
"@typescript-eslint/parser": "^6.18.1",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"eslint": "^8.56.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/exit-hook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"@alwatr/nano-build": "workspace:^",
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
2 changes: 1 addition & 1 deletion packages/flatomise/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"@alwatr/nano-build": "workspace:^",
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
2 changes: 1 addition & 1 deletion packages/global-scope/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"@alwatr/nano-build": "workspace:^",
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
2 changes: 1 addition & 1 deletion packages/is-number/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"@alwatr/nano-build": "workspace:^",
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
2 changes: 1 addition & 1 deletion packages/logger/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"@alwatr/nano-build": "workspace:^",
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
2 changes: 1 addition & 1 deletion packages/node-fs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@alwatr/type-helper": "workspace:^",
"@types/node": "^20.10.8",
"@types/node": "^20.11.3",
"typescript": "^5.3.3"
}
}
36 changes: 36 additions & 0 deletions packages/parse-duration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Parse-duration

A simple utility to parse a duration string into milliseconds number.

## Installation

```bash
yarn add @alwatr/parse-duration
```

## Usage

```js
import {parseDuration} from '@alwatr/parse-duration';

parseDuration('10s'); // 10,000
parseDuration('10m'); // 600,000
parseDuration('10h'); // 36,000,000
parseDuration('10d'); // 864,000,000
parseDuration('10w'); // 6,048,000,000
parseDuration('10M'); // 25,920,000,000
parseDuration('10y'); // 315,360,000,000
parseDuration('10d', 'h'); // 240
```

### Unit Table

| Unit | Description |
|------|--------|
| `s` | Second |
| `m` | Minute |
| `h` | Hour |
| `d` | Day |
| `w` | Week |
| `M` | Month |
| `y` | Year |
83 changes: 83 additions & 0 deletions packages/parse-duration/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"name": "@alwatr/parse-duration",
"version": "1.0.0-alpha.0",
"description": "A simple utility to parse a duration string into milliseconds number.",
"author": "S. Ali Mihandoost <[email protected]>",
"keywords": [
"parse",
"duration",
"time",
"parse-duration",
"cross-platform",
"ECMAScript",
"typescript",
"javascript",
"node",
"nodejs",
"browser",
"esm",
"module",
"utility",
"util",
"utils",
"nanolib",
"alwatr"
],
"type": "module",
"main": "./dist/main.cjs",
"module": "./dist/main.mjs",
"types": "./dist/main.d.ts",
"exports": {
".": {
"import": "./dist/main.mjs",
"require": "./dist/main.cjs",
"types": "./dist/main.d.ts"
}
},
"license": "MIT",
"files": [
"**/*.{js,mjs,cjs,map,d.ts,html,md}",
"!demo/**/*"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/Alwatr/nanolib",
"directory": "packages/parse-duration"
},
"homepage": "https://github.com/Alwatr/nanolib/tree/next/packages/parse-duration#readme",
"bugs": {
"url": "https://github.com/Alwatr/nanolib/issues"
},
"prettier": "@alwatr/prettier-config",
"scripts": {
"b": "yarn run build",
"t": "yarn run test",
"w": "yarn run watch",
"c": "yarn run clean",
"cb": "yarn run clean && yarn run build",
"d": "yarn run build:es && yarn node --enable-source-maps --trace-warnings",
"build": "yarn run build:ts & yarn run build:es",
"build:es": "nano-build --preset=module",
"build:ts": "tsc --build",
"test": "NODE_OPTIONS=\"$NODE_OPTIONS --enable-source-maps --experimental-vm-modules\" jest",
"watch": "yarn run watch:ts & yarn run watch:es",
"watch:es": "yarn run build:es --watch",
"watch:ts": "yarn run build:ts --watch --preserveWatchOutput",
"clean": "rm -rfv dist *.tsbuildinfo"
},
"dependencies": {
"@alwatr/is-number": "workspace:^"
},
"devDependencies": {
"@alwatr/nano-build": "workspace:^",
"@alwatr/prettier-config": "workspace:^",
"@alwatr/tsconfig-base": "workspace:^",
"@types/jest": "^29.5.11",
"@types/node": "^20.11.3",
"jest": "^29.7.0",
"typescript": "^5.3.3"
}
}
38 changes: 38 additions & 0 deletions packages/parse-duration/src/main.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {parseDuration} from '@alwatr/parse-duration';

describe('@alwatr/parse-duration', () => {
it('should parse duration in seconds', () => {
expect(parseDuration('5s')).toBe(5 * 1000);
});

it('should parse duration in minutes', () => {
expect(parseDuration('3m')).toBe(3 * 60 * 1000);
});

it('should parse duration in hours', () => {
expect(parseDuration('2h')).toBe(2 * 60 * 60 * 1000);
});

it('should convert duration to specified unit', () => {
expect(parseDuration('2h', 'm')).toBe(2 * 60);
});

it('should convert duration to different units', () => {
expect(parseDuration('1d', 'h')).toBe(24);
expect(parseDuration('1w', 'd')).toBe(7);
expect(parseDuration('1M', 'm')).toBe(30 * 24 * 60);
expect(parseDuration('1y', 'd')).toBe(365);
});

it('should throw error for invalid duration', () => {
expect(() => parseDuration('1x')).toThrow('invalid_unit');
});

it('should throw error for invalid conversion unit', () => {
expect(() => parseDuration('1h', 'x')).toThrow('invalid_unit');
});

it('should throw error for non-numeric duration', () => {
expect(() => parseDuration('xh')).toThrow('not_a_number');
});
});
59 changes: 59 additions & 0 deletions packages/parse-duration/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {isNumber} from '@alwatr/is-number';

/**
* Unit conversion table
*/
const unitConversion_ = {
s: 1_000,
m: 60_000,
h: 3_600_000,
d: 86_400_000,
w: 604_800_000,
M: 2_592_000_000,
y: 31_536_000_000,
} as const;

/**
* Duration unit: `s` for seconds, `m` for minutes, `h` for hours, `d` for days, `w` for weeks, `M` for months, `y` for years.
*/
export type DurationUnit = keyof typeof unitConversion_;

/**
* Duration string format: `number + unit`, for example `10m` means 10 minutes.
*/
export type DurationString = `${number}${DurationUnit}`;

/**
* Parse duration string to milliseconds number.
*
* @param duration - duration string, for example `10m` means 10 minutes.
* @param toUnit - convert to unit, default is `ms` for milliseconds.
* @return duration in milliseconds.
* @example
* ```ts
* parseDuration('10m'); // 600000
* parseDuration('10m', 's'); // 600
* ```
*/
export const parseDuration = (duration: DurationString, toUnit?: DurationUnit): number => {
const durationNumberStr = duration.slice(0, duration.length - 1);
if (!isNumber(durationNumberStr)) {
throw new Error(`not_a_number`);
}
const durationNumber = +durationNumberStr;
const durationUnit = duration.slice(-1) as DurationUnit;
const factor = unitConversion_[durationUnit];
if (factor === undefined) {
throw new Error(`invalid_unit`, {cause: {duration}});
}
const ms = durationNumber * factor;
if (toUnit === undefined) {
return ms;
}
// else
const toFactor = unitConversion_[toUnit];
if (toFactor === undefined) {
throw new Error(`invalid_unit`, {cause: {toUnit}});
}
return ms / toFactor;
};
13 changes: 13 additions & 0 deletions packages/parse-duration/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "@alwatr/tsconfig-base/tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",
"emitDeclarationOnly": true,
"composite": true,
},
"include": ["src/**/*.ts"],
"references": [
{"path": "../is-number"}
]
}
Loading