├── tslint.json ├── .gitignore ├── .editorconfig ├── .github └── workflows │ ├── ci.yml │ └── publish.yml ├── CHANGELOG.md ├── tsconfig.json ├── CONTRIBUTING.md ├── tools ├── gh-pages-publish.ts └── semantic-release-prepare.ts ├── LICENSE ├── rollup.config.ts ├── code-of-conduct.md ├── package.json ├── test ├── nepali-date-converter.test.ts └── nepali-date-helper.test.ts ├── README.md └── src ├── nepali-date-helper.ts ├── nepali-date-converter.ts └── date-config.ts /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | #root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | max_line_length = 100 10 | indent_size = 2 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [16.x, 18.x, 20.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: npm ci 24 | - run: npm run build 25 | - run: npm run test 26 | - run: npm run lint 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## v3.3.0 4 | 5 | - Safari/Firefox support 6 | - Code refactor and package size reduction 7 | - CDN support 8 | - Increase spec coverage 9 | 10 | ## v3.2.1 11 | 12 | - Added prototype methods `toValue()` and `toString()` 13 | 14 | ## v3.2.0 15 | 16 | - Feature to parse nepali date formats in constructor. 17 | 18 | ## v3.1.0 19 | 20 | - Feature to support custom user date formats. 21 | 22 | ## v3.0.0 23 | 24 | - Library rewrite 25 | - Typescript support 26 | 27 | **Note: The change log is only maintained from v3.0.0 and the version below it are not supported and not recommended.** 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"es2015", 6 | "lib": ["es2015", "es2016", "es2017", "dom"], 7 | "strict": true, 8 | "sourceMap": true, 9 | "declaration": true, 10 | "allowSyntheticDefaultImports": true, 11 | "experimentalDecorators": true, 12 | "emitDecoratorMetadata": true, 13 | "strictPropertyInitialization": false, 14 | "declarationDir": "dist/types", 15 | "outDir": "dist/lib", 16 | "typeRoots": [ 17 | "node_modules/@types" 18 | ] 19 | }, 20 | "include": [ 21 | "src" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏 2 | 3 | ## Instructions 4 | 5 | These steps will guide you through contributing to this project: 6 | 7 | - Fork the repo 8 | - Clone it and install dependencies 9 | 10 | git clone https://github.com/YOUR-USERNAME/typescript-library-starter 11 | npm install 12 | 13 | Keep in mind that after running `npm install` the git repo is reset. So a good way to cope with this is to have a copy of the folder to push the changes, and the other to try them. 14 | 15 | Make and commit your changes. Make sure the commands npm run build and npm run test:prod are working. 16 | 17 | Finally send a [GitHub Pull Request](https://github.com/alexjoverm/typescript-library-starter/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit). 18 | -------------------------------------------------------------------------------- /tools/gh-pages-publish.ts: -------------------------------------------------------------------------------- 1 | const { cd, exec, echo, touch } = require("shelljs") 2 | const { readFileSync } = require("fs") 3 | const url = require("url") 4 | 5 | let repoUrl 6 | let pkg = JSON.parse(readFileSync("package.json") as any) 7 | if (typeof pkg.repository === "object") { 8 | if (!pkg.repository.hasOwnProperty("url")) { 9 | throw new Error("URL does not exist in repository section") 10 | } 11 | repoUrl = pkg.repository.url 12 | } else { 13 | repoUrl = pkg.repository 14 | } 15 | 16 | let parsedUrl = url.parse(repoUrl) 17 | let repository = (parsedUrl.host || "") + (parsedUrl.path || "") 18 | let ghToken = process.env.GH_TOKEN 19 | 20 | echo("Deploying docs!!!") 21 | cd("docs") 22 | touch(".nojekyll") 23 | exec("git init") 24 | exec("git add .") 25 | exec('git config user.name "Subesh Bhandari"') 26 | exec('git config user.email "subeshb1@gmail.com"') 27 | exec('git commit -m "docs(docs): update gh-pages"') 28 | exec( 29 | `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages` 30 | ) 31 | echo("Docs deployed!!") 32 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: "Publish" 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | 9 | 10 | permissions: 11 | id-token: write 12 | contents: write 13 | packages: write 14 | 15 | jobs: 16 | deploy: 17 | runs-on: ubuntu-latest 18 | name: "${{ github.ref_name }} " 19 | env: 20 | GH_TOKEN: ${{ secrets.ACCESS_TOKEN_GITHUB }} 21 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 22 | steps: 23 | - uses: actions/checkout@v3 24 | 25 | - name: Use Node.js 16.x 26 | uses: actions/setup-node@v2 27 | with: 28 | node-version: 16.x 29 | registry-url: 'https://registry.npmjs.org' 30 | 31 | - run: npm ci 32 | 33 | - run: npm run test 34 | 35 | - run: npm run build 36 | 37 | - name: Publish 38 | run: npm run semantic-release 39 | env: 40 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 41 | NPM_CONFIG_REGISTRY: https://registry.npmjs.org:8443/ 42 | 43 | - name: Deploy docs 44 | run: npm run deploy-docs 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Subesh Bhandari 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /rollup.config.ts: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve' 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import sourceMaps from 'rollup-plugin-sourcemaps' 4 | import camelCase from 'lodash.camelcase' 5 | import typescript from 'rollup-plugin-typescript2' 6 | import json from 'rollup-plugin-json' 7 | 8 | const pkg = require('./package.json') 9 | 10 | const libraryName = 'nepali-date-converter' 11 | 12 | export default { 13 | input: `src/${libraryName}.ts`, 14 | output: [ 15 | { file: pkg.main, name: 'NepaliDate', format: 'umd', sourcemap: true }, 16 | { file: pkg.module, format: 'es', sourcemap: true }, 17 | ], 18 | // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') 19 | external: [], 20 | watch: { 21 | include: 'src/**', 22 | }, 23 | plugins: [ 24 | // Allow json resolution 25 | json(), 26 | // Compile TypeScript files 27 | typescript({ useTsconfigDeclarationDir: true }), 28 | // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) 29 | commonjs(), 30 | // Allow node_modules resolution, so you can use 'external' to control 31 | // which external modules to include in the bundle 32 | // https://github.com/rollup/rollup-plugin-node-resolve#usage 33 | resolve(), 34 | 35 | // Resolve source maps to the original source 36 | sourceMaps(), 37 | ], 38 | } 39 | -------------------------------------------------------------------------------- /tools/semantic-release-prepare.ts: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { fork } = require("child_process") 3 | const colors = require("colors") 4 | 5 | const { readFileSync, writeFileSync } = require("fs") 6 | const pkg = JSON.parse( 7 | readFileSync(path.resolve(__dirname, "..", "package.json")) 8 | ) 9 | 10 | pkg.scripts.prepush = "npm run test:prod && npm run build" 11 | pkg.scripts.commitmsg = "commitlint -E HUSKY_GIT_PARAMS" 12 | 13 | writeFileSync( 14 | path.resolve(__dirname, "..", "package.json"), 15 | JSON.stringify(pkg, null, 2) 16 | ) 17 | 18 | // Call husky to set up the hooks 19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "lib", "installer", 'bin'), ['install']) 20 | 21 | console.log() 22 | console.log(colors.green("Done!!")) 23 | console.log() 24 | 25 | if (pkg.repository.url.trim()) { 26 | console.log(colors.cyan("Now run:")) 27 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 28 | console.log(colors.cyan(" semantic-release-cli setup")) 29 | console.log() 30 | console.log( 31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 32 | ) 33 | console.log() 34 | console.log( 35 | colors.gray( 36 | 'Note: Make sure "repository.url" in your package.json is correct before' 37 | ) 38 | ) 39 | } else { 40 | console.log( 41 | colors.red( 42 | 'First you need to set the "repository.url" property in package.json' 43 | ) 44 | ) 45 | console.log(colors.cyan("Then run:")) 46 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 47 | console.log(colors.cyan(" semantic-release-cli setup")) 48 | console.log() 49 | console.log( 50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 51 | ) 52 | } 53 | 54 | console.log() 55 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nepali-date-converter", 3 | "version": "3.3.2", 4 | "description": "", 5 | "keywords": [ 6 | "nepali", 7 | "nepali-date", 8 | "nepali-date-converter", 9 | "date-converter", 10 | "ad-bs", 11 | "ad-to-bs", 12 | "bs-ad", 13 | "bikram-sambat", 14 | "typescript", 15 | "javascript", 16 | "BS date", 17 | "AD to BS", 18 | "Bikram Sambat Calendar" 19 | ], 20 | "main": "dist/nepali-date-converter.umd.js", 21 | "module": "dist/nepali-date-converter.es5.js", 22 | "typings": "dist/types/nepali-date-converter.d.ts", 23 | "files": [ 24 | "dist" 25 | ], 26 | "author": "Subesh Bhandari ", 27 | "repository": { 28 | "type": "git", 29 | "url": "https://github.com/subeshb1/Nepali-Date" 30 | }, 31 | "license": "MIT", 32 | "engines": { 33 | "node": ">=6.0.0" 34 | }, 35 | "scripts": { 36 | "lint": "tslint --project tsconfig.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts'", 37 | "prebuild": "rimraf dist", 38 | "build": "tsc --module commonjs && rollup -c rollup.config.ts && typedoc --out docs src/nepali-date-converter.ts", 39 | "start": "rollup -c rollup.config.ts -w", 40 | "test": "jest", 41 | "test-coverage": "jest", 42 | "test:watch": "jest --coverage --watch", 43 | "test:prod": "npm run lint && npm run test-coverage -- --no-cache", 44 | "deploy-docs": "ts-node tools/gh-pages-publish", 45 | "report-coverage": "cat ./coverage/lcov.info | coveralls", 46 | "commit": "git-cz", 47 | "semantic-release": "semantic-release", 48 | "semantic-release-prepare": "ts-node tools/semantic-release-prepare", 49 | "precommit": "lint-staged", 50 | "prepush": "npm run test:prod && npm run build", 51 | "commitmsg": "commitlint -E HUSKY_GIT_PARAMS" 52 | }, 53 | "lint-staged": { 54 | "{src,test}/**/*.ts": [ 55 | "prettier --write", 56 | "git add" 57 | ] 58 | }, 59 | "config": { 60 | "commitizen": { 61 | "path": "node_modules/cz-conventional-changelog" 62 | } 63 | }, 64 | "jest": { 65 | "transform": { 66 | ".(ts|tsx)": "ts-jest" 67 | }, 68 | "testEnvironment": "node", 69 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", 70 | "moduleFileExtensions": [ 71 | "ts", 72 | "tsx", 73 | "js" 74 | ], 75 | "coveragePathIgnorePatterns": [ 76 | "/node_modules/", 77 | "/test/" 78 | ], 79 | "coverageThreshold": { 80 | "global": { 81 | "branches": 90, 82 | "functions": 95, 83 | "lines": 95, 84 | "statements": 95 85 | } 86 | }, 87 | "collectCoverageFrom": [ 88 | "src/*.{js,ts}" 89 | ] 90 | }, 91 | "prettier": { 92 | "semi": false, 93 | "singleQuote": true 94 | }, 95 | "commitlint": { 96 | "extends": [ 97 | "@commitlint/config-conventional" 98 | ] 99 | }, 100 | "devDependencies": { 101 | "@commitlint/cli": "^17.0.3", 102 | "@commitlint/config-conventional": "^17.0.3", 103 | "@types/jest": "^28.1.6", 104 | "@types/node": "^18.6.3", 105 | "colors": "^1.4.0", 106 | "commitizen": "^4.2.5", 107 | "coveralls": "^3.1.1", 108 | "cross-env": "^7.0.3", 109 | "cz-conventional-changelog": "^3.3.0", 110 | "husky": "^8.0.1", 111 | "jest": "^28.1.3", 112 | "jest-config": "^28.1.3", 113 | "lint-staged": "^13.0.3", 114 | "lodash.camelcase": "^4.3.0", 115 | "prettier": "^2.7.1", 116 | "prompt": "^1.3.0", 117 | "replace-in-file": "^6.3.5", 118 | "rimraf": "^3.0.2", 119 | "rollup": "^2.77.2", 120 | "rollup-plugin-commonjs": "^9.1.8", 121 | "rollup-plugin-json": "^3.1.0", 122 | "rollup-plugin-node-resolve": "^3.4.0", 123 | "rollup-plugin-sourcemaps": "^0.6.3", 124 | "rollup-plugin-typescript2": "^0.32.1", 125 | "semantic-release": "^19.0.3", 126 | "shelljs": "^0.8.5", 127 | "ts-jest": "^28.0.7", 128 | "ts-node": "^10.9.1", 129 | "tslint": "^5.20.1", 130 | "tslint-config-prettier": "^1.18.0", 131 | "tslint-config-standard": "^8.0.1", 132 | "typedoc": "^0.25.12", 133 | "typescript": "^4.7.4" 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /test/nepali-date-converter.test.ts: -------------------------------------------------------------------------------- 1 | import NepaliDate from '../src/nepali-date-converter' 2 | 3 | describe('NepaliDate to English', () => { 4 | it('tests constructor', () => { 5 | const now = new Date() 6 | expect(new NepaliDate().getAD()).toEqual({ 7 | date: now.getDate(), 8 | day: now.getDay(), 9 | year: now.getFullYear(), 10 | month: now.getMonth(), 11 | }) 12 | expect(new NepaliDate(2054, 10, 10).getDateObject()).toEqual({ 13 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 14 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 15 | }) 16 | expect(new NepaliDate('2054 11 10').getDateObject()).toEqual({ 17 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 18 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 19 | }) 20 | expect(new NepaliDate('2054/11/10').getDateObject()).toEqual({ 21 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 22 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 23 | }) 24 | expect(new NepaliDate(new Date(1998, 1, 22)).getDateObject()).toEqual({ 25 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 26 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 27 | }) 28 | expect(new NepaliDate(new Date(1998, 1, 22).getTime()).getDateObject()).toEqual({ 29 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 30 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 31 | }) 32 | 33 | expect(new NepaliDate(new Date(2024, 5, 14).getTime()).getDateObject()).toEqual({ 34 | AD: { date: 14, day: 5, month: 5, year: 2024 }, 35 | BS: { date: 32, day: 5, month: 1, year: 2081 }, 36 | }) 37 | }) 38 | 39 | it('tests getters', () => { 40 | const date = new NepaliDate(2077, 10, 10) 41 | expect(date.getDay()).toEqual(1) 42 | expect(date.getDate()).toEqual(10) 43 | expect(date.getMonth()).toEqual(10) 44 | expect(date.getYear()).toEqual(2077) 45 | expect(date.getDateObject()).toEqual({ 46 | AD: { date: 22, day: 1, month: 1, year: 2021 }, 47 | BS: { date: 10, day: 1, month: 10, year: 2077 }, 48 | }) 49 | expect(date.getBS()).toEqual({ date: 10, day: 1, month: 10, year: 2077 }) 50 | expect(date.getAD()).toEqual({ date: 22, day: 1, month: 1, year: 2021 }) 51 | }) 52 | 53 | it('tests setters', () => { 54 | let date = new NepaliDate(2077, 10, 10) 55 | date.setDate(20) 56 | expect(date.getDate()).toEqual(20) 57 | date.setDate(60) 58 | expect(date.getDate()).toEqual(31) 59 | expect(date.getMonth()).toEqual(11) 60 | expect(date.getYear()).toEqual(2077) 61 | date.setMonth(2) 62 | expect(date.getMonth()).toEqual(2) 63 | date.setMonth(12) 64 | expect(date.getMonth()).toEqual(0) 65 | expect(date.getYear()).toEqual(2078) 66 | date.setYear(2056) 67 | expect(date.getYear()).toEqual(2056) 68 | }) 69 | 70 | it('tests static methods', () => { 71 | const now = new Date() 72 | expect(NepaliDate.now().getAD()).toEqual({ 73 | date: now.getDate(), 74 | day: now.getDay(), 75 | year: now.getFullYear(), 76 | month: now.getMonth(), 77 | }) 78 | expect(NepaliDate.parse('2054 11 10').getDateObject()).toEqual({ 79 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 80 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 81 | }) 82 | expect(NepaliDate.parse('2054/11/10').getDateObject()).toEqual({ 83 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 84 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 85 | }) 86 | expect(NepaliDate.fromAD(new Date(1998, 1, 22)).getDateObject()).toEqual({ 87 | AD: { date: 22, day: 0, month: 1, year: 1998 }, 88 | BS: { date: 10, day: 0, month: 10, year: 2054 }, 89 | }) 90 | }) 91 | 92 | describe('tests formatting', () => { 93 | it('Formats the date in English format.', () => { 94 | // First Date 95 | expect(new NepaliDate(2020, 0, 21).format('DD/MM/YYYY', 'en')).toEqual('21/01/2020') 96 | 97 | expect(new NepaliDate(2020, 0, 21).format('dd M/D/YYYY', 'en')).toEqual('Sat 1/21/2020') 98 | 99 | expect(new NepaliDate(2020, 0, 21).format('To\\day is dd M/D/YYYY', 'en')).toEqual( 100 | 'Today is Sat 1/21/2020' 101 | ) 102 | }) 103 | it('Formats the date in Nepali format.', () => { 104 | // First Date 105 | expect(new NepaliDate(2020, 0, 21).format('DD/MM/YYYY', 'np')).toEqual('२१/०१/२०२०') 106 | 107 | expect(new NepaliDate(2020, 0, 21).format('dd M/D/YYYY', 'np')).toEqual('शनि १/२१/२०२०') 108 | 109 | expect(new NepaliDate(2020, 0, 21).format('To\\day is dd M/D/YYYY', 'np')).toEqual( 110 | 'Today is शनि १/२१/२०२०' 111 | ) 112 | }) 113 | }) 114 | 115 | it('testing prototypes ', () => { 116 | const nd = new NepaliDate(2054, 5, 24) 117 | expect(typeof +nd).toBe('number') 118 | expect('Friday 24, Aswin 2054').toEqual(nd.toString()) 119 | }) 120 | }) 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nepali-Date 2 | 3 | A small Javascript/Typescript Library to convert English Date to Nepali and Vice Versa. 4 | 5 | [![Publish](https://github.com/subeshb1/Nepali-Date/actions/workflows/publish.yml/badge.svg)](https://github.com/subeshb1/Nepali-Date/actions/workflows/publish.yml) ![Release version](https://img.shields.io/github/v/release/subeshb1/nepali-date) 6 | 7 | ## Installation 8 | 9 | CDN: 10 | 11 | ```html 12 | 13 | ``` 14 | 15 | Node JS: 16 | 17 | ```sh 18 | npm i nepali-date-converter 19 | ``` 20 | 21 | ```js 22 | import NepaliDate from 'nepali-date-converter' 23 | // or 24 | 25 | const NepaliDate = require('nepali-date-converter') 26 | ``` 27 | 28 | Deno: 29 | 30 | ```js 31 | import NepaliDate from 'https://cdn.jsdelivr.net/npm/nepali-date-converter/dist/nepali-date-converter.es5.js' 32 | ``` 33 | 34 | ## Basic Usage 35 | 36 | ```js 37 | // NepaliDate (year,month,date) 38 | let date1 = new NepaliDate(2054, 5, 24) 39 | // Javascript Date object 40 | new NepaliDate(2051, 5, 24).toJsDate() 41 | // formatting 42 | date1.format('ddd, DD MMMM YYYY') // 'Monday, 24 Aswin 2051' 43 | // update date 44 | date1.setDate(10) 45 | date1.setMonth(1) 46 | date1.setYear(2054) 47 | ``` 48 | 49 | ## API 50 | 51 | ### Constructors 52 | 53 | #### constructor(value?: string | number | Date) 54 | 55 | **String** 56 | 57 | Provide a valid Nepali date string. The current supported formats are: 58 | 59 | ``` 60 | YYYY/MM/DD 61 | YYYY-MM-DD 62 | YYYY MM DD 63 | DD/MM/YYYY 64 | DD-MM-YYYY 65 | DD MM YYYY 66 | ``` 67 | 68 | Example: 69 | 70 | ```js 71 | new NepaliDate('2051/02/01') // YYYY/MM/DD 72 | new NepaliDate('2051-02-01') 73 | new NepaliDate('2051 02 01') 74 | new NepaliDate('01/02/2051') // DD/MM/YYYY 75 | new NepaliDate('01-02-2051') 76 | new NepaliDate('01 02 2051') 77 | ``` 78 | 79 | **Number** 80 | 81 | The number value represents the UTC timestamp that will be converted to Nepali date. 82 | 83 | Example: 84 | 85 | ```js 86 | new NepaliDate(1589638162879) 87 | ``` 88 | 89 | **Date** 90 | 91 | Javascript Date object 92 | 93 | Example: 94 | 95 | ```js 96 | new NepaliDate(new Date(2020, 10, 10)) 97 | ``` 98 | 99 | **Empty constructor** 100 | 101 | If no values are provided, the current day date will be converted to Nepali date. 102 | 103 | ```js 104 | new NepaliDate() 105 | ``` 106 | 107 | #### constructor(year: number, monthIndex: number, date: number) 108 | 109 | This constructor takes year, monthIndex i.e 0-11, and date. 110 | 111 | Example: 112 | 113 | ```js 114 | new NepaliDate(2051, 0, 1) // This date represents Baisakh 1, 2051 115 | ``` 116 | 117 | ### getYear(): number 118 | 119 | Get Nepali date year. 120 | 121 | ### getMonth(): number 122 | 123 | Get Nepali month index. 124 | 125 | ``` 126 | Baisakh => 0 127 | Jestha => 1 128 | Asar => 2 129 | Shrawan => 3 130 | Bhadra => 4 131 | Aswin => 5 132 | Kartik => 6 133 | Mangsir => 7 134 | Poush => 8 135 | Magh => 9 136 | Falgun => 10 137 | Chaitra => 11 138 | ``` 139 | 140 | ### getDate(): number 141 | 142 | Get Nepali date for the month 143 | 144 | ### getDay(): number 145 | 146 | Get Week day index for the date. 147 | 148 | ### toJsDate(): Date 149 | 150 | Returns Javascript Date converted from nepali date. 151 | 152 | ### getBS(): IYearMonthDate 153 | 154 | Returns Nepali date fields in an object implementing IYearMonthDate 155 | 156 | ```js 157 | { 158 | year: 2052, 159 | month: 10, 160 | date: 10, 161 | day: 0 162 | } 163 | ``` 164 | 165 | ### getAD(): IYearMonthDate 166 | 167 | Returns AD date fields in an object implementing IYearMonthDate 168 | 169 | Example: 170 | 171 | ```js 172 | { 173 | year: 2019, 174 | month: 10, 175 | date: 10, 176 | day: 0 177 | } 178 | ``` 179 | 180 | ### getDateObject(): IAdBs 181 | 182 | Returns an object with AD and BS object implementing IYearMonthDate 183 | 184 | Example: 185 | 186 | ```js 187 | { 188 | BS: { 189 | year: 2052, 190 | month: 10, 191 | date: 10, 192 | day: 0 193 | }, 194 | AD: { 195 | year: 2019, 196 | month: 10, 197 | date: 10, 198 | day: 0 199 | }, 200 | 201 | } 202 | ``` 203 | 204 | ### format(formatString: string, language: 'np' | 'en'): string 205 | 206 | Format Nepali date string based on format string. 207 | 208 | ``` 209 | YYYY - 4 digit of year (2077) 210 | YYY - 3 digit of year (077) 211 | YY - 2 digit of year (77) 212 | M - month number (1 - 12) 213 | MM - month number with 0 padding (01 - 12) 214 | MMM - short month name (Bai, Jes, Asa, Shr, etc.) 215 | MMMM - full month name (Baisakh, Jestha, Asar, ...) 216 | D - Day of Month (1, 2, ... 31, 32) 217 | DD - Day of Month with zero padding (01, 02, ...) 218 | d - Week day (0, 1, 2, 3, 4, 5, 6) 219 | dd - Week day in short format (Sun, Mon, ..) 220 | ddd - Week day in long format (Sunday, Monday, ...) 221 | ``` 222 | 223 | Set language to 'np' for nepali format. The strings can be combined in any way to create desired format. 224 | 225 | ```js 226 | let a = new NepaliDate(2054, 10, 10) 227 | a.format('YYYY/MM/DD') // '2054/11/10' 228 | a.format('YYYY MM DD') // '2054 11 10' 229 | a.format('YYYY') // '2054' 230 | a.format('ddd DD, MMMM YYYY') // 'Sunday 10, Falgun 2054' 231 | a.format('To\\day is ddd DD, MMMM YYYY') // 'Today is Sunday 10, Falgun 2054', Note: use '\\' to escape [YMDd] 232 | a.format('DD/MM/YYYY', 'np') //' १०/११/२०५४' 233 | a.format('dd', 'np') // 'आइतबार' 234 | a.format('ddd DD, MMMM YYYY', 'np') // 'आइतबार १०, फाल्गुण २०५४' 235 | // Set static variable to 'np' for default Nepali language 236 | NepaliDate.language = 'np' 237 | a.format('ddd DD, MMMM YYYY') // 'आइतबार १०, फाल्गुण २०५४' 238 | ``` 239 | 240 | ### setYear(year: number) 241 | 242 | Set year in the current date object. It only takes positive value i.e Nepali Year 243 | 244 | Example: 245 | 246 | ```js 247 | let a = new NepaliDate(2054, 10, 10) 248 | a.setYear(2053) // will make date NepaliDate(2053,10,15); 249 | ``` 250 | 251 | ### setMonth(month: number) 252 | 253 | Set month in the current date object. It can be positive or negative. Positive values within the month 254 | will update the month only and more then month mill increment month and year. Negative value will deduct month and year depending on the value. 255 | It is similar to javascript Date API. 256 | 257 | Example: 258 | 259 | ```js 260 | let a = new NepaliDate(2054, 10, 10) 261 | a.setMonth(1) // will make date NepaliDate(2054,1,10); 262 | a.setMonth(-1) // will make date NepaliDate(2053,11,10); To go back to previous month(s) in same or previous year 263 | a.setMonth(12) // will make date NepaliDate(2054,0,10); To go ahead to coming month(s) in same or coming year 264 | ``` 265 | 266 | ### setDate(date: number) 267 | 268 | Set date in the current date object. It can be positive or negative. Positive values within the month 269 | will update the date only and more then month mill increment month and year. Negative value will deduct month and year depending on the value. 270 | It is similar to javascript Date API. 271 | 272 | Example: 273 | 274 | ```js 275 | let a = new NepaliDate(2054, 10, 10) 276 | a.setDate(11) // will make date NepaliDate(2054,10,11); 277 | a.setDate(-1) // will make date NepaliDate(2054,9,29); To go back to dates from previous months 278 | a.setDate(45) // will make date NepaliDate(2054,10,15); To go ahead to dates in coming months 279 | ``` 280 | 281 | ### static parse(dateString: string): NepaliDate 282 | 283 | Returns new Nepali Date from the string date format 284 | Similar to calling constructor with string parameter 285 | 286 | ### static now(): NepaliDate 287 | 288 | Returns new Nepali Date converted form current day date. 289 | Similar to calling empty constructor 290 | 291 | ### static fromAD(date: Date): NepaliDate 292 | 293 | Returns new converted Nepali Date from the provided Javascript Date. 294 | It is similar to passing string as constructor 295 | 296 | ## Fixing dates and adding future data 297 | 298 | The length of month can change for the future dates. Update the `date-config-ts` files with the number of days in respective months to fix the issue. Order the data in ascending order 299 | 300 | ### Accessing the date config 301 | 302 | There might be a case where you need to access the date config to get the number of days in a month for a specific year. 303 | 304 | To access the date config, you can use the following code: 305 | 306 | ```ts 307 | import { dateConfigMap } from 'nepali-date-converter' 308 | 309 | dateConfigMap['2078'] 310 | ``` 311 | 312 | Access a specific month for a year 313 | 314 | ```ts 315 | dateConfigMap['2078'].Mangsir 316 | ``` 317 | 318 | ## Contributing Guide 319 | 320 | ```bash 321 | # Fork the repo 322 | https://github.com/subeshb1/Nepali-Date 323 | 324 | # Clone your forked repo 325 | $ git clone git@github.com:subeshb1/Nepali-Date.git 326 | 327 | $ npm install 328 | 329 | # Create a new branch for you. 330 | $ git pull origin master # Pull the latest master 331 | $ git checkout new-branch # Checkout to your new branch 332 | 333 | # Run test 334 | npm run test 335 | 336 | # Commit the changes 337 | $ npm run commit 338 | 339 | # Push your changes and 340 | $ git push 341 | 342 | # Make a pull request of your newly changed branch 343 | [https://github.com/subeshb1/Nepali-Date/compare](https://github.com/subeshb1/Nepali-Date/compare) 344 | 345 | ``` 346 | 347 | ## Maintainer 348 | 349 | - [Subesh Bhandari](https://twitter.com/subesh1) 350 | -------------------------------------------------------------------------------- /src/nepali-date-helper.ts: -------------------------------------------------------------------------------- 1 | import { dateConfigMap } from './date-config' 2 | 3 | export enum Language { 4 | np = 'np', 5 | en = 'en', 6 | } 7 | export interface IYearMonthDate { 8 | year: number 9 | month: number 10 | date: number 11 | day?: number 12 | } 13 | 14 | export interface IAdBs { 15 | AD: IYearMonthDate 16 | BS: IYearMonthDate 17 | } 18 | 19 | /** 20 | * The constant storing nepali date month days mappings for each year starting from 2000 BS 21 | */ 22 | const yearMonthDaysMapping: number[][] = Object.values(dateConfigMap).map((year) => 23 | Object.values(year) 24 | ) 25 | 26 | /** 27 | * Memoizing the days passed for each month in year for faster calculation 28 | */ 29 | const monthDaysMappings: number[][][] = yearMonthDaysMapping.map((yearMappings: number[]) => { 30 | let daySum = 0 31 | return yearMappings.map((monthDays: number) => { 32 | const monthPassedDays = [monthDays, daySum] 33 | daySum += monthDays 34 | return monthPassedDays 35 | }) 36 | }, []) 37 | 38 | /** 39 | * Ignore 40 | */ 41 | let daysPassed = 0 42 | /** 43 | * Memoizing the days passed after each year from the epoch time and the sum of days in a year 44 | */ 45 | const yearDaysMapping: number[][] = yearMonthDaysMapping.map((yearMappings: number[]) => { 46 | const daysInYear = yearMappings.reduce((acc, x) => acc + x, 0) 47 | const yearDaysPassed = [daysInYear, daysPassed] 48 | daysPassed += daysInYear 49 | return yearDaysPassed 50 | }) 51 | 52 | /** 53 | * Max possible Day 54 | */ 55 | const MAX_DAY = 33238 56 | 57 | if (daysPassed !== MAX_DAY) { 58 | throw new Error('Invalid constant initialization for Nepali Date.') 59 | } 60 | 61 | /** 62 | * Min possible Day 63 | */ 64 | const MIN_DAY = 1 65 | /** 66 | * @ignore 67 | */ 68 | export function getYearIndex(year: number) { 69 | return year - EPOCH_YEAR 70 | } 71 | 72 | /** 73 | * @ignore 74 | */ 75 | export function getYearFromIndex(yearIndex: number) { 76 | return yearIndex + EPOCH_YEAR 77 | } 78 | 79 | /** 80 | * @ignore 81 | */ 82 | export const KTM_TIMEZONE_OFFSET = 20700000 83 | /** 84 | * @ignore 85 | */ 86 | export const EPOCH_YEAR = 2000 87 | /** 88 | * @ignore 89 | */ 90 | export const COMPLETED_DAYS = 1 91 | /** 92 | * @ignore 93 | */ 94 | export const TOTAL_DAYS = 0 95 | 96 | /** 97 | * @ignore 98 | */ 99 | function mod(m: number, val: number) { 100 | while (val < 0) { 101 | val += m 102 | } 103 | return val % m 104 | } 105 | /** 106 | * Format Object 107 | */ 108 | export const formatObj = { 109 | en: { 110 | day: { 111 | short: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 112 | long: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 113 | }, 114 | month: { 115 | short: ['Bai', 'Jes', 'Asa', 'Shr', 'Bhd', 'Asw', 'Kar', 'Man', 'Pou', 'Mag', 'Fal', 'Cha'], 116 | long: [ 117 | 'Baisakh', 118 | 'Jestha', 119 | 'Asar', 120 | 'Shrawan', 121 | 'Bhadra', 122 | 'Aswin', 123 | 'Kartik', 124 | 'Mangsir', 125 | 'Poush', 126 | 'Magh', 127 | 'Falgun', 128 | 'Chaitra', 129 | ], 130 | }, 131 | date: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], 132 | }, 133 | np: { 134 | day: { 135 | short: ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'], 136 | long: ['आइतबार', 'सोमबार', 'मंगलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'], 137 | }, 138 | month: { 139 | short: ['बै', 'जे', 'अ', 'श्रा', 'भा', 'आ', 'का', 'मं', 'पौ', 'मा', 'फा', 'चै'], 140 | long: [ 141 | 'बैशाख', 142 | 'जेठ', 143 | 'असार', 144 | 'श्रावण', 145 | 'भाद्र', 146 | 'आश्विन', 147 | 'कार्तिक', 148 | 'मंसिर', 149 | 'पौष', 150 | 'माघ', 151 | 'फाल्गुण', 152 | 'चैत्र', 153 | ], 154 | }, 155 | date: ['०', '१', '२', '३', '४', '५', '६', '७', '८', '९'], 156 | }, 157 | } 158 | 159 | /** 160 | * Epoch in english date 161 | */ 162 | const beginEnglish = { 163 | year: 1943, 164 | month: 3, 165 | date: 13, 166 | day: 3, 167 | } 168 | 169 | /** 170 | * `findPassedDays` calculates the days passed from the epoch time. 171 | * If the days are beyond boundary MIN_DAY and MAX_DAY throws error. 172 | * @param year Year between 2000-2009 of nepali date 173 | * @param month Month Index which can be negative or positive and can be any number but should be within range of year 2000-2090 174 | * @param date Date which can be negative or positive and can be any number but should be within range of year 2000-2090 175 | * @returns Number of days passed since epoch time from the given date,month and year. 176 | */ 177 | export function findPassedDays(year: number, month: number, date: number) { 178 | try { 179 | const yearIndex = getYearIndex(year) 180 | const pastYearDays = yearDaysMapping[yearIndex][COMPLETED_DAYS] 181 | const extraMonth = mod(12, month) 182 | const extraYear = Math.floor(month / 12) 183 | 184 | const pastMonthDays = 185 | yearDaysMapping[yearIndex + extraYear][COMPLETED_DAYS] - 186 | pastYearDays + 187 | monthDaysMappings[yearIndex + extraYear][extraMonth][COMPLETED_DAYS] 188 | 189 | const daysPassed = pastYearDays + pastMonthDays + date 190 | if (daysPassed < MIN_DAY || daysPassed > MAX_DAY) { 191 | throw new Error() 192 | } 193 | return daysPassed 194 | } catch { 195 | throw new Error("The date doesn't fall within 2000/01/01 - 2090/12/30") 196 | } 197 | } 198 | 199 | export { monthDaysMappings, yearDaysMapping } 200 | 201 | /** 202 | * `mapDaysToDate` finds the date where the the given day lies from the epoch date 203 | * If the daysPassed is on the date 2000/01/01 then it will be 1. Similarly, every day adds on from then 204 | * If the days are beyond boundary MIN_DAY and MAX_DAY throws error. 205 | * @param daysPassed The number of days passed since nepali date epoch time 206 | * @returns date values in object implementing IYearMonthDate interface 207 | */ 208 | export function mapDaysToDate(daysPassed: number): IYearMonthDate { 209 | if (daysPassed < MIN_DAY || daysPassed > MAX_DAY) { 210 | throw new Error(`The epoch difference is not within the boundaries ${MIN_DAY} - ${MAX_DAY}`) 211 | } 212 | 213 | const yearIndex = yearDaysMapping.findIndex( 214 | (year) => 215 | daysPassed > year[COMPLETED_DAYS] && daysPassed <= year[COMPLETED_DAYS] + year[TOTAL_DAYS] 216 | ) 217 | const monthRemainder = daysPassed - yearDaysMapping[yearIndex][COMPLETED_DAYS] 218 | const monthIndex = monthDaysMappings[yearIndex].findIndex( 219 | (month) => 220 | monthRemainder > month[COMPLETED_DAYS] && 221 | monthRemainder <= month[COMPLETED_DAYS] + month[TOTAL_DAYS] 222 | ) 223 | const date = monthRemainder - monthDaysMappings[yearIndex][monthIndex][COMPLETED_DAYS] 224 | 225 | return { 226 | year: getYearFromIndex(yearIndex), 227 | month: monthIndex, 228 | date: date, 229 | } 230 | } 231 | 232 | export function findPassedDaysAD(year: number, month: number, date: number) { 233 | const timeDiff = Math.abs( 234 | Date.UTC(year, month, date) - Date.UTC(beginEnglish.year, beginEnglish.month, beginEnglish.date) 235 | ) 236 | const diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)) 237 | return diffDays 238 | } 239 | 240 | export function mapDaysToDateAD(daysPassed: number) { 241 | const mappedDate = new Date(Date.UTC(1943, 3, 13 + daysPassed)) 242 | return { 243 | year: mappedDate.getUTCFullYear(), 244 | month: mappedDate.getUTCMonth(), 245 | date: mappedDate.getUTCDate(), 246 | day: mappedDate.getUTCDay(), 247 | } 248 | } 249 | 250 | export function convertToAD(bsDateObject: IYearMonthDate): IAdBs { 251 | try { 252 | const daysPassed = findPassedDays(bsDateObject.year, bsDateObject.month, bsDateObject.date) 253 | const BS = mapDaysToDate(daysPassed) 254 | const AD = mapDaysToDateAD(daysPassed) 255 | 256 | return { 257 | AD, 258 | BS: { ...BS, day: AD.day }, 259 | } 260 | } catch { 261 | throw new Error("The date doesn't fall within 2000/01/01 - 2090/12/30") 262 | } 263 | } 264 | 265 | export function convertToBS(adDateObject: Date): IAdBs { 266 | try { 267 | const daysPassed = findPassedDaysAD( 268 | adDateObject.getFullYear(), 269 | adDateObject.getMonth(), 270 | adDateObject.getDate() 271 | ) 272 | const BS = mapDaysToDate(daysPassed) 273 | const AD = mapDaysToDateAD(daysPassed) 274 | 275 | return { 276 | AD, 277 | BS: { ...BS, day: AD.day }, 278 | } 279 | } catch { 280 | throw new Error("The date doesn't fall within 2000/01/01 - 2090/12/30") 281 | } 282 | } 283 | 284 | function mapLanguageNumber(dateNumber: string, language: 'en' | 'np'): string { 285 | return dateNumber 286 | .split('') 287 | .map((num) => formatObj[language].date[parseInt(num, 10)]) 288 | .join('') 289 | } 290 | 291 | export function format( 292 | bsDate: IYearMonthDate, 293 | stringFormat: string, 294 | language: 'en' | 'np' 295 | ): string { 296 | return stringFormat 297 | .replace(/((\\[MDYd])|D{1,2}|M{1,4}|Y{2,4}|d{1,3})/g, (match, _, matchedString) => { 298 | switch (match) { 299 | case 'D': 300 | return mapLanguageNumber(bsDate.date.toString(), language) 301 | case 'DD': 302 | return mapLanguageNumber(bsDate.date.toString().padStart(2, '0'), language) 303 | case 'M': 304 | return mapLanguageNumber((bsDate.month + 1).toString(), language) 305 | case 'MM': 306 | return mapLanguageNumber((bsDate.month + 1).toString().padStart(2, '0'), language) 307 | case 'MMM': 308 | return formatObj[language].month.short[bsDate.month] 309 | case 'MMMM': 310 | return formatObj[language].month.long[bsDate.month] 311 | case 'YY': 312 | return mapLanguageNumber(bsDate.year.toString().slice(-2), language) 313 | case 'YYY': 314 | return mapLanguageNumber(bsDate.year.toString().slice(-3), language) 315 | case 'YYYY': 316 | return mapLanguageNumber(bsDate.year.toString(), language) 317 | case 'd': 318 | return mapLanguageNumber(bsDate.day?.toString() || '0', language) 319 | case 'dd': 320 | return formatObj[language].day.short[bsDate.day || 0] 321 | case 'ddd': 322 | return formatObj[language].day.long[bsDate.day || 0] 323 | default: 324 | return matchedString.replace('/', '') 325 | } 326 | }) 327 | .replace(/\\/g, '') 328 | } 329 | 330 | export function parse(dateString: string): IYearMonthDate { 331 | const OFFICIAL_FORMAT = /(\d{4})\s*([/-]|\s+)\s*(\d{1,2})\s*([/-]|\s+)\s*(\d{1,2})/ 332 | const GEORGIAN_FORMAT = /(\d{1,2})\s*([/-]|\s+)\s*(\d{1,2})\s*([/-]|\s+)\s*(\d{4})/ 333 | let match: RegExpMatchArray | null 334 | match = dateString.match(OFFICIAL_FORMAT) 335 | if (match !== null) { 336 | return { 337 | year: parseInt(match[1], 10), 338 | month: parseInt(match[3], 10) - 1, 339 | date: parseInt(match[5], 10), 340 | } 341 | } 342 | match = dateString.match(GEORGIAN_FORMAT) 343 | if (match !== null) { 344 | return { 345 | year: parseInt(match[5], 10), 346 | month: parseInt(match[3], 10) - 1, 347 | date: parseInt(match[1], 10), 348 | } 349 | } 350 | throw new Error('Invalid date format') 351 | } 352 | -------------------------------------------------------------------------------- /src/nepali-date-converter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | convertToAD, 3 | convertToBS, 4 | IYearMonthDate, 5 | IAdBs, 6 | format, 7 | Language, 8 | parse, 9 | } from './nepali-date-helper' 10 | 11 | const dateSymbol = Symbol('Date') 12 | const daySymbol = Symbol('Day') 13 | const yearSymbol = Symbol('Year') 14 | const monthSymbol = Symbol('MonthIndex') 15 | const jsDateSymbol = Symbol('JsDate') 16 | const convertToBSMethod = Symbol('convertToBS()') 17 | const convertToADMethod = Symbol('convertToAD()') 18 | const setAdBs = Symbol('setADBS()') 19 | const setDayYearMonth = Symbol('setDayYearMonth()') 20 | 21 | export * from './date-config' 22 | export default class NepaliDate { 23 | private [jsDateSymbol]: Date 24 | private [yearSymbol]: number 25 | private [dateSymbol]: number 26 | private [daySymbol]: number 27 | private [monthSymbol]: number 28 | /** 29 | * Default language for formatting. Set the value to 'np' for default nepali formatting. 30 | */ 31 | static language: 'np' | 'en' = Language.en 32 | /** 33 | * **String** 34 | * 35 | * Provide a valid Nepali date string. The current supported formats are: 36 | * 37 | * ``` 38 | * YYYY/MM/DD 39 | * YYYY-MM-DD 40 | * YYYY MM DD 41 | * DD/MM/YYYY 42 | * DD-MM-YYYY 43 | * DD MM YYYY 44 | * ``` 45 | * 46 | * Example: 47 | * 48 | * ```js 49 | * new NepaliDate('2051/02/01') // YYYY/MM/DD 50 | * new NepaliDate('2051-02-01') 51 | * new NepaliDate('2051 02 01') 52 | * new NepaliDate('01/02/2051') // DD/MM/YYYY 53 | * new NepaliDate('01-02-2051') 54 | * new NepaliDate('01 02 2051') 55 | * ``` 56 | * 57 | * **Number** 58 | * 59 | * The number value represents the UTC timestamp that will be converted to Nepali date. 60 | * 61 | * Example: 62 | * 63 | * ```js 64 | * new NepaliDate(1589638162879) 65 | * ``` 66 | * 67 | * **Date** 68 | * 69 | * Javascript Date object 70 | * 71 | * Example: 72 | * 73 | * ```js 74 | * new NepaliDate(new Date(2020, 10, 10)) 75 | * ``` 76 | * 77 | * **Empty constructor** 78 | * 79 | * If no values are provided, the current day date will be converted to Nepali date. 80 | * 81 | * ```js 82 | * new NepaliDate() 83 | * ``` 84 | * @param value 85 | */ 86 | constructor(value?: string | number | Date) 87 | /** 88 | * This constructor takes year, monthIndex i.e 0-11, and date. 89 | * 90 | * Example: 91 | * 92 | * ```js 93 | * new Date(2051, 0, 1) // Baisakh 1, 2051 94 | * ``` 95 | * @param year 96 | * @param monthIndex 97 | * @param date 98 | */ 99 | constructor(year: number, monthIndex: number, date: number) 100 | constructor() { 101 | const constructorError = new Error('Invalid constructor arguments') 102 | if (arguments.length === 0) { 103 | this[convertToBSMethod](new Date()) 104 | } else if (arguments.length === 1) { 105 | const argument = arguments[0] 106 | switch (typeof argument) { 107 | case 'number': 108 | this[convertToBSMethod](new Date(argument)) 109 | break 110 | case 'string': 111 | const { date, year, month } = parse(argument) 112 | this[setDayYearMonth](year, month, date) 113 | this[convertToADMethod]() 114 | break 115 | case 'object': 116 | if (argument instanceof Date) { 117 | this[convertToBSMethod](argument) 118 | } else { 119 | throw constructorError 120 | } 121 | break 122 | default: 123 | throw constructorError 124 | } 125 | } else if (arguments.length <= 3) { 126 | this[setDayYearMonth](arguments[0], arguments[1], arguments[2]) 127 | this[convertToADMethod]() 128 | } else { 129 | throw constructorError 130 | } 131 | } 132 | 133 | private [setDayYearMonth](year: number, month: number = 0, date: number = 1, day: number = 0) { 134 | this[yearSymbol] = year 135 | this[monthSymbol] = month 136 | this[dateSymbol] = date 137 | this[daySymbol] = day 138 | } 139 | 140 | /** 141 | * Returns Javascript Date converted from nepali date. 142 | */ 143 | toJsDate(): Date { 144 | return this[jsDateSymbol] 145 | } 146 | /** 147 | * Get Nepali date for the month 148 | */ 149 | getDate(): number { 150 | return this[dateSymbol] 151 | } 152 | /** 153 | * Get Nepali date year. 154 | */ 155 | getYear(): number { 156 | return this[yearSymbol] 157 | } 158 | 159 | /** 160 | * Get Week day index for the date. 161 | */ 162 | getDay(): number { 163 | return this[daySymbol] 164 | } 165 | 166 | /** 167 | * Get Nepali month index. 168 | * 169 | * ``` 170 | * Baisakh => 0 171 | * Jestha => 1 172 | * Asar => 2 173 | * Shrawan => 3 174 | * Bhadra => 4 175 | * Aswin => 5 176 | * Kartik => 6 177 | * Mangsir => 7 178 | * Poush => 8 179 | * Magh => 9 180 | * Falgun => 10 181 | * Chaitra => 11 182 | * ``` 183 | */ 184 | getMonth(): number { 185 | return this[monthSymbol] 186 | } 187 | 188 | /** 189 | * Returns an object with AD and BS object implementing IYearMonthDate 190 | * 191 | * Example: 192 | * 193 | * ```js 194 | * { 195 | * BS: { 196 | * year: 2052, 197 | * month: 10, 198 | * date: 10, 199 | * day: 0 200 | * }, 201 | * AD: { 202 | * year: 2019, 203 | * month: 10, 204 | * date: 10, 205 | * day: 0 206 | * }, 207 | * 208 | * } 209 | * ``` 210 | */ 211 | getDateObject(): IAdBs { 212 | return { 213 | BS: this.getBS(), 214 | AD: this.getAD(), 215 | } 216 | } 217 | /** 218 | * Returns Nepali date fields in an object implementing IYearMonthDate 219 | * 220 | * ```js 221 | * { 222 | * year: 2052, 223 | * month: 10, 224 | * date: 10, 225 | * day: 0 226 | * } 227 | * ``` 228 | */ 229 | getBS(): IYearMonthDate { 230 | return { 231 | year: this[yearSymbol], 232 | month: this[monthSymbol], 233 | date: this[dateSymbol], 234 | day: this[daySymbol], 235 | } 236 | } 237 | /** 238 | * Returns AD date fields in an object implementing IYearMonthDate 239 | * 240 | * ```js 241 | * { 242 | * year: 2019, 243 | * month: 10, 244 | * date: 10, 245 | * day: 0 246 | * } 247 | * ``` 248 | */ 249 | getAD(): IYearMonthDate { 250 | return { 251 | year: this[jsDateSymbol].getFullYear(), 252 | month: this[jsDateSymbol].getMonth(), 253 | date: this[jsDateSymbol].getDate(), 254 | day: this[jsDateSymbol].getDay(), 255 | } 256 | } 257 | 258 | /** 259 | * Set date in the current date object. It can be positive or negative. Positive values within the month 260 | * will update the date only and more then month mill increment month and year. Negative value will deduct month and year depending on the value. 261 | * It is similar to javascript Date API. 262 | * 263 | * Example: 264 | * ```js 265 | * let a = new NepaliDate(2054,10,10); 266 | * a.setDate(11); // will make date NepaliDate(2054,10,11); 267 | * a.setDate(-1); // will make date NepaliDate(2054,9,29); 268 | * a.setDate(45); // will make date NepaliDate(2054,10,15); 269 | * ``` 270 | * @param date positive or negative integer value to set date 271 | */ 272 | setDate(date: number) { 273 | const oldDate = this[dateSymbol] 274 | try { 275 | this[dateSymbol] = date 276 | this[convertToADMethod]() 277 | } catch (e) { 278 | this[dateSymbol] = oldDate 279 | throw e 280 | } 281 | } 282 | 283 | /** 284 | * Set month in the current date object. It can be positive or negative. Positive values within the month 285 | * will update the month only and more then month mill increment month and year. Negative value will deduct month and year depending on the value. 286 | * It is similar to javascript Date API. 287 | * 288 | * Example: 289 | * ```js 290 | * let a = new NepaliDate(2054,10,10); 291 | * a.setMonth(1); // will make date NepaliDate(2054,11,10); 292 | * a.setMonth(-1); // will make date NepaliDate(2053,11,10); 293 | * a.setMonth(12); // will make date NepaliDate(2054,0,10); 294 | * ``` 295 | * @param date positive or negative integer value to set month 296 | */ 297 | setMonth(month: number) { 298 | const oldMonth = this[monthSymbol] 299 | try { 300 | this[monthSymbol] = month 301 | this[convertToADMethod]() 302 | } catch (e) { 303 | this[monthSymbol] = oldMonth 304 | throw e 305 | } 306 | } 307 | 308 | /** 309 | * Set year in the current date object. It only takes positive value i.e Nepali Year 310 | * 311 | * Example: 312 | * ```js 313 | * let a = new NepaliDate(2054,10,10); 314 | * a.setYear(2053); // will make date NepaliDate(2053,10,15); 315 | * ``` 316 | * @param date positive integer value to set year 317 | */ 318 | setYear(year: number) { 319 | const oldYear = this[yearSymbol] 320 | try { 321 | this[yearSymbol] = year 322 | this[convertToADMethod]() 323 | } catch (e) { 324 | this[yearSymbol] = oldYear 325 | throw e 326 | } 327 | } 328 | 329 | /** 330 | * Format Nepali date string based on format string. 331 | * ``` 332 | * YYYY - 4 digit of year (2077) 333 | * YYY - 3 digit of year (077) 334 | * YY - 2 digit of year (77) 335 | * M - month number (1 - 12) 336 | * MM - month number with 0 padding (01 - 12) 337 | * MMM - short month name (Bai, Jes, Asa, Shr, etc.) 338 | * MMMM - full month name (Baisakh, Jestha, Asar, ...) 339 | * D - Day of Month (1, 2, ... 31, 32) 340 | * DD - Day of Month with zero padding (01, 02, ...) 341 | * d - Week day (0, 1, 2, 3, 4, 5, 6) 342 | * dd - Week day in short format (Sun, Mon, ..) 343 | * ddd - Week day in long format (Sunday, Monday, ...) 344 | * ``` 345 | * Set language to 'np' for nepali format. The strings can be combined in any way to create desired format. 346 | * ```js 347 | * let a = new NepaliDate(2054,10,10); 348 | * a.format('YYYY/MM/DD') // '2054/11/10' 349 | * a.format('YYYY MM DD') // '2054 11 10' 350 | * a.format('YYYY') // '2054' 351 | * a.format('ddd DD, MMMM YYYY') // 'Sunday 10, Falgun 2054' 352 | * a.format('To\\day is ddd DD, MMMM YYYY') // 'Today is Sunday 10, Falgun 2054', Note: use '\\' to escape [YMDd] 353 | * a.format('DD/MM/YYYY', 'np') //' १०/११/२०५४' 354 | * a.format('dd', 'np') // 'आइतबार' 355 | * a.format('ddd DD, MMMM YYYY','np') // 'आइतबार १०, फाल्गुण २०५४' 356 | * // Set static variable to 'np' for default Nepali language 357 | * NepaliDate.language = 'np' 358 | * a.format('ddd DD, MMMM YYYY') // 'आइतबार १०, फाल्गुण २०५४' 359 | * ``` 360 | * @param formatString 361 | * @param language en | np 362 | */ 363 | format(formatString: string, language: 'en' | 'np' = NepaliDate.language): string { 364 | return format(this.getBS(), formatString, language) 365 | } 366 | 367 | /** 368 | * Returns new Nepali Date from the string date format 369 | * Similar to calling constructor with string parameter 370 | * @param dateString 371 | */ 372 | static parse(dateString: string): NepaliDate { 373 | const { date, year, month } = parse(dateString) 374 | return new NepaliDate(year, month, date) 375 | } 376 | 377 | /** 378 | * Returns new Nepali Date converted form current day date. 379 | * Similar to calling empty constructor 380 | */ 381 | static now(): NepaliDate { 382 | return new NepaliDate() 383 | } 384 | 385 | /** 386 | * Returns new converted Nepali Date from the provided Javascript Date. 387 | * It is similar to passing string as constructor 388 | * @param date 389 | */ 390 | static fromAD(date: Date): NepaliDate { 391 | return new NepaliDate(date) 392 | } 393 | 394 | private [convertToBSMethod](date: Date) { 395 | const { AD, BS } = convertToBS(date) 396 | this[setAdBs](AD, BS) 397 | } 398 | 399 | private [setAdBs](AD: IYearMonthDate, BS: IYearMonthDate) { 400 | this[setDayYearMonth](BS.year, BS.month, BS.date, BS.day) 401 | this[jsDateSymbol] = new Date(AD.year, AD.month, AD.date) 402 | } 403 | 404 | private [convertToADMethod]() { 405 | const { AD, BS } = convertToAD({ 406 | year: this[yearSymbol], 407 | month: this[monthSymbol], 408 | date: this[dateSymbol], 409 | }) 410 | this[setAdBs](AD, BS) 411 | } 412 | 413 | valueOf() { 414 | return this[jsDateSymbol].getTime() 415 | } 416 | 417 | toString() { 418 | return this.format('ddd DD, MMMM YYYY') 419 | } 420 | } 421 | -------------------------------------------------------------------------------- /test/nepali-date-helper.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | parse, 3 | monthDaysMappings, 4 | yearDaysMapping, 5 | Language, 6 | findPassedDays, 7 | COMPLETED_DAYS, 8 | TOTAL_DAYS, 9 | getYearIndex, 10 | mapDaysToDate, 11 | format 12 | } from '../src/nepali-date-helper' 13 | 14 | const Baisakh = 0 15 | const Jestha = 1 16 | const Asar = 2 17 | const Shrawan = 3 18 | const Bhadra = 4 19 | const Aswin = 5 20 | const Kartik = 6 21 | const Mangsir = 7 22 | const Poush = 8 23 | const Magh = 9 24 | const Falgun = 10 25 | const Chaitra = 11 26 | 27 | describe('findPassedDays', () => { 28 | it('returns days that have passed since epoch nepali time', () => { 29 | // Normal cases where the date and month don't exceed limits 30 | expect(findPassedDays(2077, 0, 10)).toBe( 31 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 32 | monthDaysMappings[getYearIndex(2077)][Baisakh][COMPLETED_DAYS] + 33 | 10 34 | ) 35 | expect(findPassedDays(2077, 1, 10)).toBe( 36 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 37 | monthDaysMappings[getYearIndex(2077)][Jestha][COMPLETED_DAYS] + 38 | 10 39 | ) 40 | expect(findPassedDays(2077, 1, 26)).toBe( 41 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 42 | monthDaysMappings[getYearIndex(2077)][Jestha][COMPLETED_DAYS] + 43 | 26 44 | ) 45 | expect(findPassedDays(2000, 0, 1)).toBe( 46 | yearDaysMapping[getYearIndex(2000)][COMPLETED_DAYS] + 47 | monthDaysMappings[getYearIndex(2000)][Baisakh][COMPLETED_DAYS] + 48 | 1 49 | ) 50 | expect(findPassedDays(2090, 11, 30)).toBe( 51 | yearDaysMapping[getYearIndex(2090)][COMPLETED_DAYS] + 52 | monthDaysMappings[getYearIndex(2090)][Chaitra][COMPLETED_DAYS] + 53 | monthDaysMappings[getYearIndex(2090)][Chaitra][TOTAL_DAYS] 54 | ) 55 | // When month is negative 56 | expect(findPassedDays(2077, -1, 1)).toBe( 57 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 58 | monthDaysMappings[getYearIndex(2076)][Chaitra][COMPLETED_DAYS] + 59 | 1 60 | ) 61 | expect(findPassedDays(2077, -1, 30)).toBe( 62 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 63 | monthDaysMappings[getYearIndex(2076)][Chaitra][COMPLETED_DAYS] + 64 | 30 65 | ) 66 | expect(findPassedDays(2077, -10, 2)).toBe( 67 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 68 | monthDaysMappings[getYearIndex(2076)][Asar][COMPLETED_DAYS] + 69 | 2 70 | ) 71 | expect(findPassedDays(2077, -12, 2)).toBe( 72 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 73 | monthDaysMappings[getYearIndex(2076)][Baisakh][COMPLETED_DAYS] + 74 | 2 75 | ) 76 | expect(findPassedDays(2077, -13, 2)).toBe( 77 | yearDaysMapping[getYearIndex(2075)][COMPLETED_DAYS] + 78 | monthDaysMappings[getYearIndex(2075)][Chaitra][COMPLETED_DAYS] + 79 | 2 80 | ) 81 | expect(findPassedDays(2077, -24, 2)).toBe( 82 | yearDaysMapping[getYearIndex(2075)][COMPLETED_DAYS] + 83 | monthDaysMappings[getYearIndex(2075)][Baisakh][COMPLETED_DAYS] + 84 | 2 85 | ) 86 | expect(findPassedDays(2077, -24, 365 * 2 + 1)).toBe( 87 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 88 | monthDaysMappings[getYearIndex(2077)][Baisakh][COMPLETED_DAYS] + 89 | 1 90 | ) 91 | 92 | // case when date is 0 93 | expect(findPassedDays(2077, 1, 0)).toBe( 94 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 95 | monthDaysMappings[getYearIndex(2077)][Baisakh][COMPLETED_DAYS] + 96 | monthDaysMappings[getYearIndex(2077)][Baisakh][TOTAL_DAYS] 97 | ) 98 | expect(findPassedDays(2077, 0, 0)).toBe( 99 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 100 | monthDaysMappings[getYearIndex(2076)][Chaitra][COMPLETED_DAYS] + 101 | monthDaysMappings[getYearIndex(2076)][Chaitra][TOTAL_DAYS] 102 | ) 103 | expect(findPassedDays(2077, -480, 0)).toBe( 104 | yearDaysMapping[getYearIndex(2036)][COMPLETED_DAYS] + 105 | monthDaysMappings[getYearIndex(2036)][Chaitra][COMPLETED_DAYS] + 106 | monthDaysMappings[getYearIndex(2036)][Chaitra][TOTAL_DAYS] 107 | ) 108 | 109 | // case when date is beyond month dates 110 | expect(findPassedDays(2077, 0, 33)).toBe( 111 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 112 | monthDaysMappings[getYearIndex(2077)][Jestha][COMPLETED_DAYS] + 113 | 2 114 | ) 115 | expect(findPassedDays(2076, 0, 365)).toBe( 116 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 117 | monthDaysMappings[getYearIndex(2076)][Chaitra][COMPLETED_DAYS] + 118 | monthDaysMappings[getYearIndex(2076)][Chaitra][TOTAL_DAYS] 119 | ) 120 | expect(findPassedDays(2076, 0, 366)).toBe( 121 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 122 | monthDaysMappings[getYearIndex(2077)][Baisakh][COMPLETED_DAYS] + 123 | 1 124 | ) 125 | // case when date is negative 126 | expect(findPassedDays(2077, 0, -1)).toBe( 127 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 128 | monthDaysMappings[getYearIndex(2076)][Chaitra][COMPLETED_DAYS] + 129 | monthDaysMappings[getYearIndex(2076)][Chaitra][TOTAL_DAYS] - 130 | 1 131 | ) 132 | expect(findPassedDays(2077, 5, -10)).toBe( 133 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 134 | monthDaysMappings[getYearIndex(2077)][Bhadra][COMPLETED_DAYS] + 135 | monthDaysMappings[getYearIndex(2077)][Bhadra][TOTAL_DAYS] - 136 | 10 137 | ) 138 | expect(findPassedDays(2077, 0, -365)).toBe( 139 | yearDaysMapping[getYearIndex(2075)][COMPLETED_DAYS] + 140 | monthDaysMappings[getYearIndex(2075)][Chaitra][COMPLETED_DAYS] + 141 | monthDaysMappings[getYearIndex(2075)][Chaitra][TOTAL_DAYS] 142 | ) 143 | expect(findPassedDays(2077, 0, -364)).toBe( 144 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 145 | monthDaysMappings[getYearIndex(2076)][Baisakh][COMPLETED_DAYS] + 146 | 1 147 | ) 148 | 149 | // case when both date and month is negative 150 | expect(findPassedDays(2077, -1, -1)).toBe( 151 | yearDaysMapping[getYearIndex(2076)][COMPLETED_DAYS] + 152 | monthDaysMappings[getYearIndex(2076)][Falgun][COMPLETED_DAYS] + 153 | monthDaysMappings[getYearIndex(2076)][Falgun][TOTAL_DAYS] - 154 | 1 155 | ) 156 | expect(findPassedDays(2077, -12, -1)).toBe( 157 | yearDaysMapping[getYearIndex(2075)][COMPLETED_DAYS] + 158 | monthDaysMappings[getYearIndex(2075)][Chaitra][COMPLETED_DAYS] + 159 | monthDaysMappings[getYearIndex(2075)][Chaitra][TOTAL_DAYS] - 160 | 1 161 | ) 162 | expect(findPassedDays(2077, -480, -365)).toBe( 163 | yearDaysMapping[getYearIndex(2035)][COMPLETED_DAYS] + 164 | monthDaysMappings[getYearIndex(2035)][Chaitra][COMPLETED_DAYS] + 165 | monthDaysMappings[getYearIndex(2035)][Chaitra][TOTAL_DAYS] 166 | ) 167 | expect(findPassedDays(2077, -480, -364)).toBe( 168 | yearDaysMapping[getYearIndex(2036)][COMPLETED_DAYS] + 169 | monthDaysMappings[getYearIndex(2036)][Baisakh][COMPLETED_DAYS] + 170 | 1 171 | ) 172 | }) 173 | 174 | it("throws if the the date doesn't lie within the nepali date boundary", () => { 175 | expect(() => findPassedDays(2000, -1, -1)).toThrow( 176 | "The date doesn't fall within 2000/01/01 - 2090/12/30" 177 | ) 178 | expect(() => findPassedDays(2000, -100, -1)).toThrow( 179 | "The date doesn't fall within 2000/01/01 - 2090/12/30" 180 | ) 181 | expect(() => findPassedDays(2090, 11, 31)).toThrow( 182 | "The date doesn't fall within 2000/01/01 - 2090/12/30" 183 | ) 184 | expect(() => findPassedDays(2090, 11, 3001)).toThrow( 185 | "The date doesn't fall within 2000/01/01 - 2090/12/30" 186 | ) 187 | expect(() => findPassedDays(2000, 0, -31)).toThrow( 188 | "The date doesn't fall within 2000/01/01 - 2090/12/30" 189 | ) 190 | expect(() => findPassedDays(2091, 1, 1)).toThrow( 191 | "The date doesn't fall within 2000/01/01 - 2090/12/30" 192 | ) 193 | expect(() => findPassedDays(1999, 1, 1)).toThrow( 194 | "The date doesn't fall within 2000/01/01 - 2090/12/30" 195 | ) 196 | }) 197 | }) 198 | 199 | describe('mapDaysToDate', () => { 200 | it('maps given epoch difference to nepali date', () => { 201 | // First Date 202 | expect(mapDaysToDate(1)).toEqual({ date: 1, month: 0, year: 2000 }) 203 | // Last Date 204 | expect(mapDaysToDate(33238)).toEqual({ date: 30, month: 11, year: 2090 }) 205 | expect( 206 | mapDaysToDate( 207 | yearDaysMapping[getYearIndex(2077)][COMPLETED_DAYS] + 208 | monthDaysMappings[getYearIndex(2077)][Baisakh][COMPLETED_DAYS] + 209 | 10 210 | ) 211 | ).toEqual({ date: 10, month: 0, year: 2077 }) 212 | expect( 213 | mapDaysToDate( 214 | yearDaysMapping[getYearIndex(2054)][COMPLETED_DAYS] + 215 | monthDaysMappings[getYearIndex(2054)][Aswin][COMPLETED_DAYS] + 216 | 24 217 | ) 218 | ).toEqual({ date: 24, month: 5, year: 2054 }) 219 | }) 220 | 221 | it('throws if the difference is beyond min max boundaries', () => { 222 | expect(() => mapDaysToDate(-1)).toThrow( 223 | 'The epoch difference is not within the boundaries 1 - 33238' 224 | ) 225 | expect(() => mapDaysToDate(0)).toThrow( 226 | 'The epoch difference is not within the boundaries 1 - 33238' 227 | ) 228 | expect(() => mapDaysToDate(33239)).toThrow( 229 | 'The epoch difference is not within the boundaries 1 - 33238' 230 | ) 231 | }) 232 | 233 | describe('format', () => { 234 | it('Formats the date in English format.', () => { 235 | // First Date 236 | expect( 237 | format( 238 | { 239 | year: 2020, 240 | month: 0, 241 | date: 21, 242 | day: 6 243 | }, 244 | 'DD/MM/YYYY', 245 | Language.en 246 | ) 247 | ).toEqual('21/01/2020') 248 | 249 | expect( 250 | format( 251 | { 252 | year: 2020, 253 | month: 0, 254 | date: 21, 255 | day: 6 256 | }, 257 | 'dd M/D/YYYY', 258 | Language.en 259 | ) 260 | ).toEqual('Sat 1/21/2020') 261 | 262 | expect( 263 | format( 264 | { 265 | year: 2020, 266 | month: 0, 267 | date: 21, 268 | day: 6 269 | }, 270 | 'To\\day is dd M/D/YYYY', 271 | Language.en 272 | ) 273 | ).toEqual('Today is Sat 1/21/2020') 274 | }) 275 | it('Formats the date in Nepali format.', () => { 276 | // First Date 277 | expect( 278 | format( 279 | { 280 | year: 2020, 281 | month: 0, 282 | date: 21, 283 | day: 6 284 | }, 285 | 'DD/MM/YYYY', 286 | Language.np 287 | ) 288 | ).toEqual('२१/०१/२०२०') 289 | 290 | expect( 291 | format( 292 | { 293 | year: 2020, 294 | month: 0, 295 | date: 21, 296 | day: 6 297 | }, 298 | 'dd M/D/YYYY', 299 | Language.np 300 | ) 301 | ).toEqual('शनि १/२१/२०२०') 302 | 303 | expect( 304 | format( 305 | { 306 | year: 2020, 307 | month: 0, 308 | date: 21, 309 | day: 6 310 | }, 311 | 'To\\day is dd M/D/YYYY', 312 | Language.np 313 | ) 314 | ).toEqual('Today is शनि १/२१/२०२०') 315 | }) 316 | }) 317 | 318 | describe('parse', () => { 319 | it('Formats the date in English format.', () => { 320 | expect(() => parse('')).toThrow('Invalid date format') 321 | expect(() => parse('asda asdas')).toThrow('Invalid date format') 322 | expect(parse('2051/02/01')).toEqual({ date: 1, month: 1, year: 2051 }) 323 | expect(parse('2051-02-01')).toEqual({ date: 1, month: 1, year: 2051 }) 324 | expect(parse('2051 02 01')).toEqual({ date: 1, month: 1, year: 2051 }) 325 | expect(parse('01/02/2051')).toEqual({ date: 1, month: 1, year: 2051 }) 326 | expect(parse('01-02-2051')).toEqual({ date: 1, month: 1, year: 2051 }) 327 | expect(parse('02 - 03 - 2051')).toEqual({ date: 2, month: 2, year: 2051 }) 328 | expect(parse('01 02 2051')).toEqual({ date: 1, month: 1, year: 2051 }) 329 | expect(parse('01 02 2051')).toEqual({ 330 | date: 1, 331 | month: 1, 332 | year: 2051 333 | }) 334 | }) 335 | }) 336 | }) 337 | -------------------------------------------------------------------------------- /src/date-config.ts: -------------------------------------------------------------------------------- 1 | export type DateConfig = { 2 | [year: string]: { 3 | Baisakh: number 4 | Jestha: number 5 | Asar: number 6 | Shrawan: number 7 | Bhadra: number 8 | Aswin: number 9 | Kartik: number 10 | Mangsir: number 11 | Poush: number 12 | Magh: number 13 | Falgun: number 14 | Chaitra: number 15 | } 16 | } 17 | export const dateConfigMap: DateConfig = { 18 | '2000': { 19 | Baisakh: 30, 20 | Jestha: 32, 21 | Asar: 31, 22 | Shrawan: 32, 23 | Bhadra: 31, 24 | Aswin: 30, 25 | Kartik: 30, 26 | Mangsir: 30, 27 | Poush: 29, 28 | Magh: 30, 29 | Falgun: 29, 30 | Chaitra: 31, 31 | }, 32 | '2001': { 33 | Baisakh: 31, 34 | Jestha: 31, 35 | Asar: 32, 36 | Shrawan: 31, 37 | Bhadra: 31, 38 | Aswin: 31, 39 | Kartik: 30, 40 | Mangsir: 29, 41 | Poush: 30, 42 | Magh: 29, 43 | Falgun: 30, 44 | Chaitra: 30, 45 | }, 46 | '2002': { 47 | Baisakh: 31, 48 | Jestha: 31, 49 | Asar: 32, 50 | Shrawan: 32, 51 | Bhadra: 31, 52 | Aswin: 30, 53 | Kartik: 30, 54 | Mangsir: 29, 55 | Poush: 30, 56 | Magh: 29, 57 | Falgun: 30, 58 | Chaitra: 30, 59 | }, 60 | '2003': { 61 | Baisakh: 31, 62 | Jestha: 32, 63 | Asar: 31, 64 | Shrawan: 32, 65 | Bhadra: 31, 66 | Aswin: 30, 67 | Kartik: 30, 68 | Mangsir: 30, 69 | Poush: 29, 70 | Magh: 29, 71 | Falgun: 30, 72 | Chaitra: 31, 73 | }, 74 | '2004': { 75 | Baisakh: 30, 76 | Jestha: 32, 77 | Asar: 31, 78 | Shrawan: 32, 79 | Bhadra: 31, 80 | Aswin: 30, 81 | Kartik: 30, 82 | Mangsir: 30, 83 | Poush: 29, 84 | Magh: 30, 85 | Falgun: 29, 86 | Chaitra: 31, 87 | }, 88 | '2005': { 89 | Baisakh: 31, 90 | Jestha: 31, 91 | Asar: 32, 92 | Shrawan: 31, 93 | Bhadra: 31, 94 | Aswin: 31, 95 | Kartik: 30, 96 | Mangsir: 29, 97 | Poush: 30, 98 | Magh: 29, 99 | Falgun: 30, 100 | Chaitra: 30, 101 | }, 102 | '2006': { 103 | Baisakh: 31, 104 | Jestha: 31, 105 | Asar: 32, 106 | Shrawan: 32, 107 | Bhadra: 31, 108 | Aswin: 30, 109 | Kartik: 30, 110 | Mangsir: 29, 111 | Poush: 30, 112 | Magh: 29, 113 | Falgun: 30, 114 | Chaitra: 30, 115 | }, 116 | '2007': { 117 | Baisakh: 31, 118 | Jestha: 32, 119 | Asar: 31, 120 | Shrawan: 32, 121 | Bhadra: 31, 122 | Aswin: 30, 123 | Kartik: 30, 124 | Mangsir: 30, 125 | Poush: 29, 126 | Magh: 29, 127 | Falgun: 30, 128 | Chaitra: 31, 129 | }, 130 | '2008': { 131 | Baisakh: 31, 132 | Jestha: 31, 133 | Asar: 31, 134 | Shrawan: 32, 135 | Bhadra: 31, 136 | Aswin: 31, 137 | Kartik: 29, 138 | Mangsir: 30, 139 | Poush: 30, 140 | Magh: 29, 141 | Falgun: 29, 142 | Chaitra: 31, 143 | }, 144 | '2009': { 145 | Baisakh: 31, 146 | Jestha: 31, 147 | Asar: 32, 148 | Shrawan: 31, 149 | Bhadra: 31, 150 | Aswin: 31, 151 | Kartik: 30, 152 | Mangsir: 29, 153 | Poush: 30, 154 | Magh: 29, 155 | Falgun: 30, 156 | Chaitra: 30, 157 | }, 158 | '2010': { 159 | Baisakh: 31, 160 | Jestha: 31, 161 | Asar: 32, 162 | Shrawan: 32, 163 | Bhadra: 31, 164 | Aswin: 30, 165 | Kartik: 30, 166 | Mangsir: 29, 167 | Poush: 30, 168 | Magh: 29, 169 | Falgun: 30, 170 | Chaitra: 30, 171 | }, 172 | '2011': { 173 | Baisakh: 31, 174 | Jestha: 32, 175 | Asar: 31, 176 | Shrawan: 32, 177 | Bhadra: 31, 178 | Aswin: 30, 179 | Kartik: 30, 180 | Mangsir: 30, 181 | Poush: 29, 182 | Magh: 29, 183 | Falgun: 30, 184 | Chaitra: 31, 185 | }, 186 | '2012': { 187 | Baisakh: 31, 188 | Jestha: 31, 189 | Asar: 31, 190 | Shrawan: 32, 191 | Bhadra: 31, 192 | Aswin: 31, 193 | Kartik: 29, 194 | Mangsir: 30, 195 | Poush: 30, 196 | Magh: 29, 197 | Falgun: 30, 198 | Chaitra: 30, 199 | }, 200 | '2013': { 201 | Baisakh: 31, 202 | Jestha: 31, 203 | Asar: 32, 204 | Shrawan: 31, 205 | Bhadra: 31, 206 | Aswin: 31, 207 | Kartik: 30, 208 | Mangsir: 29, 209 | Poush: 30, 210 | Magh: 29, 211 | Falgun: 30, 212 | Chaitra: 30, 213 | }, 214 | '2014': { 215 | Baisakh: 31, 216 | Jestha: 31, 217 | Asar: 32, 218 | Shrawan: 32, 219 | Bhadra: 31, 220 | Aswin: 30, 221 | Kartik: 30, 222 | Mangsir: 29, 223 | Poush: 30, 224 | Magh: 29, 225 | Falgun: 30, 226 | Chaitra: 30, 227 | }, 228 | '2015': { 229 | Baisakh: 31, 230 | Jestha: 32, 231 | Asar: 31, 232 | Shrawan: 32, 233 | Bhadra: 31, 234 | Aswin: 30, 235 | Kartik: 30, 236 | Mangsir: 30, 237 | Poush: 29, 238 | Magh: 29, 239 | Falgun: 30, 240 | Chaitra: 31, 241 | }, 242 | '2016': { 243 | Baisakh: 31, 244 | Jestha: 31, 245 | Asar: 31, 246 | Shrawan: 32, 247 | Bhadra: 31, 248 | Aswin: 31, 249 | Kartik: 29, 250 | Mangsir: 30, 251 | Poush: 30, 252 | Magh: 29, 253 | Falgun: 30, 254 | Chaitra: 30, 255 | }, 256 | '2017': { 257 | Baisakh: 31, 258 | Jestha: 31, 259 | Asar: 32, 260 | Shrawan: 31, 261 | Bhadra: 31, 262 | Aswin: 31, 263 | Kartik: 30, 264 | Mangsir: 29, 265 | Poush: 30, 266 | Magh: 29, 267 | Falgun: 30, 268 | Chaitra: 30, 269 | }, 270 | '2018': { 271 | Baisakh: 31, 272 | Jestha: 32, 273 | Asar: 31, 274 | Shrawan: 32, 275 | Bhadra: 31, 276 | Aswin: 30, 277 | Kartik: 30, 278 | Mangsir: 29, 279 | Poush: 30, 280 | Magh: 29, 281 | Falgun: 30, 282 | Chaitra: 30, 283 | }, 284 | '2019': { 285 | Baisakh: 31, 286 | Jestha: 32, 287 | Asar: 31, 288 | Shrawan: 32, 289 | Bhadra: 31, 290 | Aswin: 30, 291 | Kartik: 30, 292 | Mangsir: 30, 293 | Poush: 29, 294 | Magh: 30, 295 | Falgun: 29, 296 | Chaitra: 31, 297 | }, 298 | '2020': { 299 | Baisakh: 31, 300 | Jestha: 31, 301 | Asar: 31, 302 | Shrawan: 32, 303 | Bhadra: 31, 304 | Aswin: 31, 305 | Kartik: 30, 306 | Mangsir: 29, 307 | Poush: 30, 308 | Magh: 29, 309 | Falgun: 30, 310 | Chaitra: 30, 311 | }, 312 | '2021': { 313 | Baisakh: 31, 314 | Jestha: 31, 315 | Asar: 32, 316 | Shrawan: 31, 317 | Bhadra: 31, 318 | Aswin: 31, 319 | Kartik: 30, 320 | Mangsir: 29, 321 | Poush: 30, 322 | Magh: 29, 323 | Falgun: 30, 324 | Chaitra: 30, 325 | }, 326 | '2022': { 327 | Baisakh: 31, 328 | Jestha: 32, 329 | Asar: 31, 330 | Shrawan: 32, 331 | Bhadra: 31, 332 | Aswin: 30, 333 | Kartik: 30, 334 | Mangsir: 30, 335 | Poush: 29, 336 | Magh: 29, 337 | Falgun: 30, 338 | Chaitra: 30, 339 | }, 340 | '2023': { 341 | Baisakh: 31, 342 | Jestha: 32, 343 | Asar: 31, 344 | Shrawan: 32, 345 | Bhadra: 31, 346 | Aswin: 30, 347 | Kartik: 30, 348 | Mangsir: 30, 349 | Poush: 29, 350 | Magh: 30, 351 | Falgun: 29, 352 | Chaitra: 31, 353 | }, 354 | '2024': { 355 | Baisakh: 31, 356 | Jestha: 31, 357 | Asar: 31, 358 | Shrawan: 32, 359 | Bhadra: 31, 360 | Aswin: 31, 361 | Kartik: 30, 362 | Mangsir: 29, 363 | Poush: 30, 364 | Magh: 29, 365 | Falgun: 30, 366 | Chaitra: 30, 367 | }, 368 | '2025': { 369 | Baisakh: 31, 370 | Jestha: 31, 371 | Asar: 32, 372 | Shrawan: 31, 373 | Bhadra: 31, 374 | Aswin: 31, 375 | Kartik: 30, 376 | Mangsir: 29, 377 | Poush: 30, 378 | Magh: 29, 379 | Falgun: 30, 380 | Chaitra: 30, 381 | }, 382 | '2026': { 383 | Baisakh: 31, 384 | Jestha: 32, 385 | Asar: 31, 386 | Shrawan: 32, 387 | Bhadra: 31, 388 | Aswin: 30, 389 | Kartik: 30, 390 | Mangsir: 30, 391 | Poush: 29, 392 | Magh: 29, 393 | Falgun: 30, 394 | Chaitra: 31, 395 | }, 396 | '2027': { 397 | Baisakh: 30, 398 | Jestha: 32, 399 | Asar: 31, 400 | Shrawan: 32, 401 | Bhadra: 31, 402 | Aswin: 30, 403 | Kartik: 30, 404 | Mangsir: 30, 405 | Poush: 29, 406 | Magh: 30, 407 | Falgun: 29, 408 | Chaitra: 31, 409 | }, 410 | '2028': { 411 | Baisakh: 31, 412 | Jestha: 31, 413 | Asar: 32, 414 | Shrawan: 31, 415 | Bhadra: 31, 416 | Aswin: 31, 417 | Kartik: 30, 418 | Mangsir: 29, 419 | Poush: 30, 420 | Magh: 29, 421 | Falgun: 30, 422 | Chaitra: 30, 423 | }, 424 | '2029': { 425 | Baisakh: 31, 426 | Jestha: 31, 427 | Asar: 32, 428 | Shrawan: 31, 429 | Bhadra: 32, 430 | Aswin: 30, 431 | Kartik: 30, 432 | Mangsir: 29, 433 | Poush: 30, 434 | Magh: 29, 435 | Falgun: 30, 436 | Chaitra: 30, 437 | }, 438 | '2030': { 439 | Baisakh: 31, 440 | Jestha: 32, 441 | Asar: 31, 442 | Shrawan: 32, 443 | Bhadra: 31, 444 | Aswin: 30, 445 | Kartik: 30, 446 | Mangsir: 30, 447 | Poush: 29, 448 | Magh: 29, 449 | Falgun: 30, 450 | Chaitra: 31, 451 | }, 452 | '2031': { 453 | Baisakh: 30, 454 | Jestha: 32, 455 | Asar: 31, 456 | Shrawan: 32, 457 | Bhadra: 31, 458 | Aswin: 30, 459 | Kartik: 30, 460 | Mangsir: 30, 461 | Poush: 29, 462 | Magh: 30, 463 | Falgun: 29, 464 | Chaitra: 31, 465 | }, 466 | '2032': { 467 | Baisakh: 31, 468 | Jestha: 31, 469 | Asar: 32, 470 | Shrawan: 31, 471 | Bhadra: 31, 472 | Aswin: 31, 473 | Kartik: 30, 474 | Mangsir: 29, 475 | Poush: 30, 476 | Magh: 29, 477 | Falgun: 30, 478 | Chaitra: 30, 479 | }, 480 | '2033': { 481 | Baisakh: 31, 482 | Jestha: 31, 483 | Asar: 32, 484 | Shrawan: 32, 485 | Bhadra: 31, 486 | Aswin: 30, 487 | Kartik: 30, 488 | Mangsir: 29, 489 | Poush: 30, 490 | Magh: 29, 491 | Falgun: 30, 492 | Chaitra: 30, 493 | }, 494 | '2034': { 495 | Baisakh: 31, 496 | Jestha: 32, 497 | Asar: 31, 498 | Shrawan: 32, 499 | Bhadra: 31, 500 | Aswin: 30, 501 | Kartik: 30, 502 | Mangsir: 30, 503 | Poush: 29, 504 | Magh: 29, 505 | Falgun: 30, 506 | Chaitra: 31, 507 | }, 508 | '2035': { 509 | Baisakh: 30, 510 | Jestha: 32, 511 | Asar: 31, 512 | Shrawan: 32, 513 | Bhadra: 31, 514 | Aswin: 31, 515 | Kartik: 29, 516 | Mangsir: 30, 517 | Poush: 30, 518 | Magh: 29, 519 | Falgun: 29, 520 | Chaitra: 31, 521 | }, 522 | '2036': { 523 | Baisakh: 31, 524 | Jestha: 31, 525 | Asar: 32, 526 | Shrawan: 31, 527 | Bhadra: 31, 528 | Aswin: 31, 529 | Kartik: 30, 530 | Mangsir: 29, 531 | Poush: 30, 532 | Magh: 29, 533 | Falgun: 30, 534 | Chaitra: 30, 535 | }, 536 | '2037': { 537 | Baisakh: 31, 538 | Jestha: 31, 539 | Asar: 32, 540 | Shrawan: 32, 541 | Bhadra: 31, 542 | Aswin: 30, 543 | Kartik: 30, 544 | Mangsir: 29, 545 | Poush: 30, 546 | Magh: 29, 547 | Falgun: 30, 548 | Chaitra: 30, 549 | }, 550 | '2038': { 551 | Baisakh: 31, 552 | Jestha: 32, 553 | Asar: 31, 554 | Shrawan: 32, 555 | Bhadra: 31, 556 | Aswin: 30, 557 | Kartik: 30, 558 | Mangsir: 30, 559 | Poush: 29, 560 | Magh: 29, 561 | Falgun: 30, 562 | Chaitra: 31, 563 | }, 564 | '2039': { 565 | Baisakh: 31, 566 | Jestha: 31, 567 | Asar: 31, 568 | Shrawan: 32, 569 | Bhadra: 31, 570 | Aswin: 31, 571 | Kartik: 29, 572 | Mangsir: 30, 573 | Poush: 30, 574 | Magh: 29, 575 | Falgun: 30, 576 | Chaitra: 30, 577 | }, 578 | '2040': { 579 | Baisakh: 31, 580 | Jestha: 31, 581 | Asar: 32, 582 | Shrawan: 31, 583 | Bhadra: 31, 584 | Aswin: 31, 585 | Kartik: 30, 586 | Mangsir: 29, 587 | Poush: 30, 588 | Magh: 29, 589 | Falgun: 30, 590 | Chaitra: 30, 591 | }, 592 | '2041': { 593 | Baisakh: 31, 594 | Jestha: 31, 595 | Asar: 32, 596 | Shrawan: 32, 597 | Bhadra: 31, 598 | Aswin: 30, 599 | Kartik: 30, 600 | Mangsir: 29, 601 | Poush: 30, 602 | Magh: 29, 603 | Falgun: 30, 604 | Chaitra: 30, 605 | }, 606 | '2042': { 607 | Baisakh: 31, 608 | Jestha: 32, 609 | Asar: 31, 610 | Shrawan: 32, 611 | Bhadra: 31, 612 | Aswin: 30, 613 | Kartik: 30, 614 | Mangsir: 30, 615 | Poush: 29, 616 | Magh: 29, 617 | Falgun: 30, 618 | Chaitra: 31, 619 | }, 620 | '2043': { 621 | Baisakh: 31, 622 | Jestha: 31, 623 | Asar: 31, 624 | Shrawan: 32, 625 | Bhadra: 31, 626 | Aswin: 31, 627 | Kartik: 29, 628 | Mangsir: 30, 629 | Poush: 30, 630 | Magh: 29, 631 | Falgun: 30, 632 | Chaitra: 30, 633 | }, 634 | '2044': { 635 | Baisakh: 31, 636 | Jestha: 31, 637 | Asar: 32, 638 | Shrawan: 31, 639 | Bhadra: 31, 640 | Aswin: 31, 641 | Kartik: 30, 642 | Mangsir: 29, 643 | Poush: 30, 644 | Magh: 29, 645 | Falgun: 30, 646 | Chaitra: 30, 647 | }, 648 | '2045': { 649 | Baisakh: 31, 650 | Jestha: 32, 651 | Asar: 31, 652 | Shrawan: 32, 653 | Bhadra: 31, 654 | Aswin: 30, 655 | Kartik: 30, 656 | Mangsir: 29, 657 | Poush: 30, 658 | Magh: 29, 659 | Falgun: 30, 660 | Chaitra: 30, 661 | }, 662 | '2046': { 663 | Baisakh: 31, 664 | Jestha: 32, 665 | Asar: 31, 666 | Shrawan: 32, 667 | Bhadra: 31, 668 | Aswin: 30, 669 | Kartik: 30, 670 | Mangsir: 30, 671 | Poush: 29, 672 | Magh: 29, 673 | Falgun: 30, 674 | Chaitra: 31, 675 | }, 676 | '2047': { 677 | Baisakh: 31, 678 | Jestha: 31, 679 | Asar: 31, 680 | Shrawan: 32, 681 | Bhadra: 31, 682 | Aswin: 31, 683 | Kartik: 30, 684 | Mangsir: 29, 685 | Poush: 30, 686 | Magh: 29, 687 | Falgun: 30, 688 | Chaitra: 30, 689 | }, 690 | '2048': { 691 | Baisakh: 31, 692 | Jestha: 31, 693 | Asar: 32, 694 | Shrawan: 31, 695 | Bhadra: 31, 696 | Aswin: 31, 697 | Kartik: 30, 698 | Mangsir: 29, 699 | Poush: 30, 700 | Magh: 29, 701 | Falgun: 30, 702 | Chaitra: 30, 703 | }, 704 | '2049': { 705 | Baisakh: 31, 706 | Jestha: 32, 707 | Asar: 31, 708 | Shrawan: 32, 709 | Bhadra: 31, 710 | Aswin: 30, 711 | Kartik: 30, 712 | Mangsir: 30, 713 | Poush: 29, 714 | Magh: 29, 715 | Falgun: 30, 716 | Chaitra: 30, 717 | }, 718 | '2050': { 719 | Baisakh: 31, 720 | Jestha: 32, 721 | Asar: 31, 722 | Shrawan: 32, 723 | Bhadra: 31, 724 | Aswin: 30, 725 | Kartik: 30, 726 | Mangsir: 30, 727 | Poush: 29, 728 | Magh: 30, 729 | Falgun: 29, 730 | Chaitra: 31, 731 | }, 732 | '2051': { 733 | Baisakh: 31, 734 | Jestha: 31, 735 | Asar: 31, 736 | Shrawan: 32, 737 | Bhadra: 31, 738 | Aswin: 31, 739 | Kartik: 30, 740 | Mangsir: 29, 741 | Poush: 30, 742 | Magh: 29, 743 | Falgun: 30, 744 | Chaitra: 30, 745 | }, 746 | '2052': { 747 | Baisakh: 31, 748 | Jestha: 31, 749 | Asar: 32, 750 | Shrawan: 31, 751 | Bhadra: 31, 752 | Aswin: 31, 753 | Kartik: 30, 754 | Mangsir: 29, 755 | Poush: 30, 756 | Magh: 29, 757 | Falgun: 30, 758 | Chaitra: 30, 759 | }, 760 | '2053': { 761 | Baisakh: 31, 762 | Jestha: 32, 763 | Asar: 31, 764 | Shrawan: 32, 765 | Bhadra: 31, 766 | Aswin: 30, 767 | Kartik: 30, 768 | Mangsir: 30, 769 | Poush: 29, 770 | Magh: 29, 771 | Falgun: 30, 772 | Chaitra: 30, 773 | }, 774 | '2054': { 775 | Baisakh: 31, 776 | Jestha: 32, 777 | Asar: 31, 778 | Shrawan: 32, 779 | Bhadra: 31, 780 | Aswin: 30, 781 | Kartik: 30, 782 | Mangsir: 30, 783 | Poush: 29, 784 | Magh: 30, 785 | Falgun: 29, 786 | Chaitra: 31, 787 | }, 788 | '2055': { 789 | Baisakh: 31, 790 | Jestha: 31, 791 | Asar: 32, 792 | Shrawan: 31, 793 | Bhadra: 31, 794 | Aswin: 31, 795 | Kartik: 30, 796 | Mangsir: 29, 797 | Poush: 30, 798 | Magh: 29, 799 | Falgun: 30, 800 | Chaitra: 30, 801 | }, 802 | '2056': { 803 | Baisakh: 31, 804 | Jestha: 31, 805 | Asar: 32, 806 | Shrawan: 31, 807 | Bhadra: 32, 808 | Aswin: 30, 809 | Kartik: 30, 810 | Mangsir: 29, 811 | Poush: 30, 812 | Magh: 29, 813 | Falgun: 30, 814 | Chaitra: 30, 815 | }, 816 | '2057': { 817 | Baisakh: 31, 818 | Jestha: 32, 819 | Asar: 31, 820 | Shrawan: 32, 821 | Bhadra: 31, 822 | Aswin: 30, 823 | Kartik: 30, 824 | Mangsir: 30, 825 | Poush: 29, 826 | Magh: 29, 827 | Falgun: 30, 828 | Chaitra: 31, 829 | }, 830 | '2058': { 831 | Baisakh: 30, 832 | Jestha: 32, 833 | Asar: 31, 834 | Shrawan: 32, 835 | Bhadra: 31, 836 | Aswin: 30, 837 | Kartik: 30, 838 | Mangsir: 30, 839 | Poush: 29, 840 | Magh: 30, 841 | Falgun: 29, 842 | Chaitra: 31, 843 | }, 844 | '2059': { 845 | Baisakh: 31, 846 | Jestha: 31, 847 | Asar: 32, 848 | Shrawan: 31, 849 | Bhadra: 31, 850 | Aswin: 31, 851 | Kartik: 30, 852 | Mangsir: 29, 853 | Poush: 30, 854 | Magh: 29, 855 | Falgun: 30, 856 | Chaitra: 30, 857 | }, 858 | '2060': { 859 | Baisakh: 31, 860 | Jestha: 31, 861 | Asar: 32, 862 | Shrawan: 32, 863 | Bhadra: 31, 864 | Aswin: 30, 865 | Kartik: 30, 866 | Mangsir: 29, 867 | Poush: 30, 868 | Magh: 29, 869 | Falgun: 30, 870 | Chaitra: 30, 871 | }, 872 | '2061': { 873 | Baisakh: 31, 874 | Jestha: 32, 875 | Asar: 31, 876 | Shrawan: 32, 877 | Bhadra: 31, 878 | Aswin: 30, 879 | Kartik: 30, 880 | Mangsir: 30, 881 | Poush: 29, 882 | Magh: 29, 883 | Falgun: 30, 884 | Chaitra: 31, 885 | }, 886 | '2062': { 887 | Baisakh: 30, 888 | Jestha: 32, 889 | Asar: 31, 890 | Shrawan: 32, 891 | Bhadra: 31, 892 | Aswin: 31, 893 | Kartik: 29, 894 | Mangsir: 30, 895 | Poush: 29, 896 | Magh: 30, 897 | Falgun: 29, 898 | Chaitra: 31, 899 | }, 900 | '2063': { 901 | Baisakh: 31, 902 | Jestha: 31, 903 | Asar: 32, 904 | Shrawan: 31, 905 | Bhadra: 31, 906 | Aswin: 31, 907 | Kartik: 30, 908 | Mangsir: 29, 909 | Poush: 30, 910 | Magh: 29, 911 | Falgun: 30, 912 | Chaitra: 30, 913 | }, 914 | '2064': { 915 | Baisakh: 31, 916 | Jestha: 31, 917 | Asar: 32, 918 | Shrawan: 32, 919 | Bhadra: 31, 920 | Aswin: 30, 921 | Kartik: 30, 922 | Mangsir: 29, 923 | Poush: 30, 924 | Magh: 29, 925 | Falgun: 30, 926 | Chaitra: 30, 927 | }, 928 | '2065': { 929 | Baisakh: 31, 930 | Jestha: 32, 931 | Asar: 31, 932 | Shrawan: 32, 933 | Bhadra: 31, 934 | Aswin: 30, 935 | Kartik: 30, 936 | Mangsir: 30, 937 | Poush: 29, 938 | Magh: 29, 939 | Falgun: 30, 940 | Chaitra: 31, 941 | }, 942 | '2066': { 943 | Baisakh: 31, 944 | Jestha: 31, 945 | Asar: 31, 946 | Shrawan: 32, 947 | Bhadra: 31, 948 | Aswin: 31, 949 | Kartik: 29, 950 | Mangsir: 30, 951 | Poush: 30, 952 | Magh: 29, 953 | Falgun: 29, 954 | Chaitra: 31, 955 | }, 956 | '2067': { 957 | Baisakh: 31, 958 | Jestha: 31, 959 | Asar: 32, 960 | Shrawan: 31, 961 | Bhadra: 31, 962 | Aswin: 31, 963 | Kartik: 30, 964 | Mangsir: 29, 965 | Poush: 30, 966 | Magh: 29, 967 | Falgun: 30, 968 | Chaitra: 30, 969 | }, 970 | '2068': { 971 | Baisakh: 31, 972 | Jestha: 31, 973 | Asar: 32, 974 | Shrawan: 32, 975 | Bhadra: 31, 976 | Aswin: 30, 977 | Kartik: 30, 978 | Mangsir: 29, 979 | Poush: 30, 980 | Magh: 29, 981 | Falgun: 30, 982 | Chaitra: 30, 983 | }, 984 | '2069': { 985 | Baisakh: 31, 986 | Jestha: 32, 987 | Asar: 31, 988 | Shrawan: 32, 989 | Bhadra: 31, 990 | Aswin: 30, 991 | Kartik: 30, 992 | Mangsir: 30, 993 | Poush: 29, 994 | Magh: 29, 995 | Falgun: 30, 996 | Chaitra: 31, 997 | }, 998 | '2070': { 999 | Baisakh: 31, 1000 | Jestha: 31, 1001 | Asar: 31, 1002 | Shrawan: 32, 1003 | Bhadra: 31, 1004 | Aswin: 31, 1005 | Kartik: 29, 1006 | Mangsir: 30, 1007 | Poush: 30, 1008 | Magh: 29, 1009 | Falgun: 30, 1010 | Chaitra: 30, 1011 | }, 1012 | '2071': { 1013 | Baisakh: 31, 1014 | Jestha: 31, 1015 | Asar: 32, 1016 | Shrawan: 31, 1017 | Bhadra: 31, 1018 | Aswin: 31, 1019 | Kartik: 30, 1020 | Mangsir: 29, 1021 | Poush: 30, 1022 | Magh: 29, 1023 | Falgun: 30, 1024 | Chaitra: 30, 1025 | }, 1026 | '2072': { 1027 | Baisakh: 31, 1028 | Jestha: 32, 1029 | Asar: 31, 1030 | Shrawan: 32, 1031 | Bhadra: 31, 1032 | Aswin: 30, 1033 | Kartik: 30, 1034 | Mangsir: 29, 1035 | Poush: 30, 1036 | Magh: 29, 1037 | Falgun: 30, 1038 | Chaitra: 30, 1039 | }, 1040 | '2073': { 1041 | Baisakh: 31, 1042 | Jestha: 32, 1043 | Asar: 31, 1044 | Shrawan: 32, 1045 | Bhadra: 31, 1046 | Aswin: 30, 1047 | Kartik: 30, 1048 | Mangsir: 30, 1049 | Poush: 29, 1050 | Magh: 29, 1051 | Falgun: 30, 1052 | Chaitra: 31, 1053 | }, 1054 | '2074': { 1055 | Baisakh: 31, 1056 | Jestha: 31, 1057 | Asar: 31, 1058 | Shrawan: 32, 1059 | Bhadra: 31, 1060 | Aswin: 31, 1061 | Kartik: 30, 1062 | Mangsir: 29, 1063 | Poush: 30, 1064 | Magh: 29, 1065 | Falgun: 30, 1066 | Chaitra: 30, 1067 | }, 1068 | '2075': { 1069 | Baisakh: 31, 1070 | Jestha: 31, 1071 | Asar: 32, 1072 | Shrawan: 31, 1073 | Bhadra: 31, 1074 | Aswin: 31, 1075 | Kartik: 30, 1076 | Mangsir: 29, 1077 | Poush: 30, 1078 | Magh: 29, 1079 | Falgun: 30, 1080 | Chaitra: 30, 1081 | }, 1082 | '2076': { 1083 | Baisakh: 31, 1084 | Jestha: 32, 1085 | Asar: 31, 1086 | Shrawan: 32, 1087 | Bhadra: 31, 1088 | Aswin: 30, 1089 | Kartik: 30, 1090 | Mangsir: 30, 1091 | Poush: 29, 1092 | Magh: 29, 1093 | Falgun: 30, 1094 | Chaitra: 30, 1095 | }, 1096 | '2077': { 1097 | Baisakh: 31, 1098 | Jestha: 32, 1099 | Asar: 31, 1100 | Shrawan: 32, 1101 | Bhadra: 31, 1102 | Aswin: 30, 1103 | Kartik: 30, 1104 | Mangsir: 30, 1105 | Poush: 29, 1106 | Magh: 30, 1107 | Falgun: 29, 1108 | Chaitra: 31, 1109 | }, 1110 | '2078': { 1111 | Baisakh: 31, 1112 | Jestha: 31, 1113 | Asar: 31, 1114 | Shrawan: 32, 1115 | Bhadra: 31, 1116 | Aswin: 31, 1117 | Kartik: 30, 1118 | Mangsir: 29, 1119 | Poush: 30, 1120 | Magh: 29, 1121 | Falgun: 30, 1122 | Chaitra: 30, 1123 | }, 1124 | '2079': { 1125 | Baisakh: 31, 1126 | Jestha: 31, 1127 | Asar: 32, 1128 | Shrawan: 31, 1129 | Bhadra: 31, 1130 | Aswin: 31, 1131 | Kartik: 30, 1132 | Mangsir: 29, 1133 | Poush: 30, 1134 | Magh: 29, 1135 | Falgun: 30, 1136 | Chaitra: 30, 1137 | }, 1138 | '2080': { 1139 | Baisakh: 31, 1140 | Jestha: 32, 1141 | Asar: 31, 1142 | Shrawan: 32, 1143 | Bhadra: 31, 1144 | Aswin: 30, 1145 | Kartik: 30, 1146 | Mangsir: 30, 1147 | Poush: 29, 1148 | Magh: 29, 1149 | Falgun: 30, 1150 | Chaitra: 30, 1151 | }, 1152 | '2081': { 1153 | Baisakh: 31, 1154 | Jestha: 32, 1155 | Asar: 31, 1156 | Shrawan: 32, 1157 | Bhadra: 31, 1158 | Aswin: 30, 1159 | Kartik: 30, 1160 | Mangsir: 30, 1161 | Poush: 29, 1162 | Magh: 30, 1163 | Falgun: 29, 1164 | Chaitra: 31, 1165 | }, 1166 | '2082': { 1167 | Baisakh: 31, 1168 | Jestha: 31, 1169 | Asar: 32, 1170 | Shrawan: 31, 1171 | Bhadra: 31, 1172 | Aswin: 31, 1173 | Kartik: 30, 1174 | Mangsir: 29, 1175 | Poush: 30, 1176 | Magh: 29, 1177 | Falgun: 30, 1178 | Chaitra: 30, 1179 | }, 1180 | '2083': { 1181 | Baisakh: 31, 1182 | Jestha: 31, 1183 | Asar: 32, 1184 | Shrawan: 31, 1185 | Bhadra: 31, 1186 | Aswin: 31, 1187 | Kartik: 30, 1188 | Mangsir: 29, 1189 | Poush: 30, 1190 | Magh: 29, 1191 | Falgun: 30, 1192 | Chaitra: 30, 1193 | }, 1194 | '2084': { 1195 | Baisakh: 31, 1196 | Jestha: 32, 1197 | Asar: 31, 1198 | Shrawan: 32, 1199 | Bhadra: 31, 1200 | Aswin: 30, 1201 | Kartik: 30, 1202 | Mangsir: 30, 1203 | Poush: 29, 1204 | Magh: 29, 1205 | Falgun: 30, 1206 | Chaitra: 31, 1207 | }, 1208 | '2085': { 1209 | Baisakh: 30, 1210 | Jestha: 32, 1211 | Asar: 31, 1212 | Shrawan: 32, 1213 | Bhadra: 31, 1214 | Aswin: 30, 1215 | Kartik: 30, 1216 | Mangsir: 30, 1217 | Poush: 29, 1218 | Magh: 30, 1219 | Falgun: 29, 1220 | Chaitra: 31, 1221 | }, 1222 | '2086': { 1223 | Baisakh: 31, 1224 | Jestha: 31, 1225 | Asar: 32, 1226 | Shrawan: 31, 1227 | Bhadra: 31, 1228 | Aswin: 31, 1229 | Kartik: 30, 1230 | Mangsir: 29, 1231 | Poush: 30, 1232 | Magh: 29, 1233 | Falgun: 30, 1234 | Chaitra: 30, 1235 | }, 1236 | '2087': { 1237 | Baisakh: 31, 1238 | Jestha: 31, 1239 | Asar: 32, 1240 | Shrawan: 31, 1241 | Bhadra: 31, 1242 | Aswin: 31, 1243 | Kartik: 30, 1244 | Mangsir: 30, 1245 | Poush: 29, 1246 | Magh: 30, 1247 | Falgun: 30, 1248 | Chaitra: 30, 1249 | }, 1250 | '2088': { 1251 | Baisakh: 30, 1252 | Jestha: 31, 1253 | Asar: 32, 1254 | Shrawan: 32, 1255 | Bhadra: 30, 1256 | Aswin: 31, 1257 | Kartik: 30, 1258 | Mangsir: 30, 1259 | Poush: 29, 1260 | Magh: 30, 1261 | Falgun: 30, 1262 | Chaitra: 30, 1263 | }, 1264 | '2089': { 1265 | Baisakh: 30, 1266 | Jestha: 32, 1267 | Asar: 31, 1268 | Shrawan: 32, 1269 | Bhadra: 31, 1270 | Aswin: 30, 1271 | Kartik: 30, 1272 | Mangsir: 30, 1273 | Poush: 29, 1274 | Magh: 30, 1275 | Falgun: 30, 1276 | Chaitra: 30, 1277 | }, 1278 | '2090': { 1279 | Baisakh: 30, 1280 | Jestha: 32, 1281 | Asar: 31, 1282 | Shrawan: 32, 1283 | Bhadra: 31, 1284 | Aswin: 30, 1285 | Kartik: 30, 1286 | Mangsir: 30, 1287 | Poush: 29, 1288 | Magh: 30, 1289 | Falgun: 30, 1290 | Chaitra: 30, 1291 | }, 1292 | } 1293 | --------------------------------------------------------------------------------