Skip to content

Commit

Permalink
feat(parse-duration): add new package (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
alimd authored Jan 16, 2024
2 parents d20bcad + 86d5e47 commit 1d199b6
Show file tree
Hide file tree
Showing 20 changed files with 2,567 additions and 337 deletions.
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

0 comments on commit 1d199b6

Please sign in to comment.