├── .gitignore ├── dist └── jalali-moment.browser.js.LICENSE.txt ├── .travis.yml ├── .eslintrc ├── webpack.browser.js ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── bower.json ├── webpack.config.js ├── cli.js ├── LICENSE ├── README.fa.md ├── package.json ├── npmdoc.md ├── index.html ├── README.md ├── jalali-moment.d.ts ├── jalali-moment.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | node_modules 3 | npm-debug.log 4 | pkg 5 | .idea 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /dist/jalali-moment.browser.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | //! moment.js 2 | 3 | //! moment.js locale configuration 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | install: 3 | - yarn 4 | node_js: 5 | - '10' 6 | script: 7 | - npm run report-coverage -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "semi": ["error", "always"], 4 | "quotes": ["error", "double"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /webpack.browser.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); 3 | 4 | module.exports = { 5 | entry: "./jalali-moment.js", // string | object | array 6 | output: { 7 | path: path.resolve(__dirname, "dist"), // string 8 | filename: "jalali-moment.browser.js", // string 9 | library: "moment", // string, 10 | }, 11 | plugins: [ 12 | // new UglifyJSPlugin() 13 | ], 14 | mode: 'production', 15 | devtool: 'source-map' 16 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jalali-moment", 3 | "description": "Jalali (Persian, Khorshidi, Shamsi) calendar system to use in javascript or typescript.", 4 | "main": "jalali-moment.js", 5 | "authors": [ 6 | "Mojtaba Zarei (Fingerpich)" 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "jalali", 11 | "convert", 12 | "miladi", 13 | "shamsi", 14 | "typescript", 15 | "javascript", 16 | "persian", 17 | "khorshidi", 18 | "date", 19 | "time", 20 | "calendar" 21 | ], 22 | "homepage": "https://github.com/fingerpich/jalali-moment", 23 | "ignore": [ 24 | "**/.*", 25 | "node_modules", 26 | "bower_components", 27 | "test", 28 | "tests" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **To Create a demo** 11 | Steps to create a demo: 12 | 1. Go to [this demo template](https://stackblitz.com/edit/jalali-moment-demo-react) (the template is using jalali moment) 13 | 2. Click on Fork button 14 | 3. Change the code to reproduce the bug 15 | 4. Share and copy the url here 16 | > If you didn't create a demo we would have to close the issue, so please take your time to create a demo. 17 | 18 | **Describe the bug** 19 | A clear and concise description of what the bug is. 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); 3 | 4 | module.exports = { 5 | entry: "./jalali-moment.js", // string | object | array 6 | output: { 7 | path: path.resolve(__dirname, "dist"), // string 8 | filename: "jalali-moment.js", // string 9 | // the url to the output directory resolved relative to the HTML page 10 | library: "jalali-moment", // string, 11 | // the name of the exported library 12 | libraryTarget: "umd", // universal module definition 13 | // the type of the exported library 14 | }, 15 | mode: 'production', 16 | plugins: [ 17 | // new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /fa/), 18 | new UglifyJSPlugin() 19 | ] 20 | } -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var program = require("commander"); 3 | // var inquirer = require("inquirer"); 4 | var package = require("./package.json"); 5 | var jm = require("./jalali-moment.js"); 6 | 7 | program 8 | .version(package.version, "-v, --version"); 9 | 10 | program 11 | .command("togregorian ") 12 | .description("convert jalali date to gregorian") 13 | .option("-f, --format", "input format") 14 | .option("-o, --oformat", "output format") 15 | .action(function (date, cmd) { 16 | console.log(jm.from(date, "fa", cmd.readFormat || "YYYY/MM/DD").format(cmd.outformat || "YYYY/MM/DD")); 17 | }); 18 | 19 | program 20 | .command("tojalali ") 21 | .description("convert a gregorian date to jalali") 22 | .option("-f, --format", "input format") 23 | .option("-o, --oformat", "output format") 24 | .action(function (date, cmd) { 25 | console.log(jm(date, cmd.readFormat || "YYYY/MM/DD").locale("fa").format(cmd.outformat || "YYYY/MM/DD")); 26 | }); 27 | 28 | program.parse(process.argv); 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2017 Mojtaba Zarei 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /README.fa.md: -------------------------------------------------------------------------------- 1 | # Jalali Moment جلالی مامنت 2 | نمایش٬ تبدیل و مدیریت تاریخ شمسی٬ جلالی یا خورشیدی به میلادی یا گرگورین 3 | 4 | #### نمونه های استفاده 5 | - [دمو](https://fingerpich.github.io/jalali-moment) 6 | - [یک نمونه ساده](https://plnkr.co/edit/MBv2BBjLvIqjtMdoGdgk?p=preview) 7 | 8 | ## نحوه 9 | 10 | - [نصب کتابخانه](https://github.com/fingerpich/jalali-moment#install) 11 | - [استفاده از تاریخ شمسی در node js](https://github.com/fingerpich/jalali-moment#using-in-nodejs) 12 | - استفاده از جلالی مامنت در 13 | - [Node.js](https://github.com/fingerpich/jalali-moment#using-in-nodejs) 14 | - [React](https://github.com/fingerpich/jalali-moment#react) 15 | - [Es5](https://github.com/fingerpich/jalali-moment#es5) 16 | - [Typescript](https://github.com/fingerpich/jalali-moment#typescript) 17 | - [Angular](https://github.com/fingerpich/jalali-moment#angular) 18 | - [Aurelia](https://github.com/fingerpich/jalali-moment#aurelia) 19 | - [Vue](https://github.com/fingerpich/jalali-moment#vue) 20 | - [Terminal(Command Line)](https://github.com/fingerpich/jalali-moment#command-line) 21 | - [Jquery](https://github.com/fingerpich/jalali-moment#jquery) 22 | - [توابع تاریخ شمسی٬ جلالی٬ خورشیدی و میلادی](https://github.com/fingerpich/jalali-moment#api) 23 | - [گرفتن تاریخ از یک رشته](https://github.com/fingerpich/jalali-moment#parse) 24 | - [نمایش](https://github.com/fingerpich/jalali-moment#display-jalali-or-miladi-date) 25 | - [تغییر](https://github.com/fingerpich/jalali-moment#manipulate) 26 | - [بررسی صحت](https://github.com/fingerpich/jalali-moment#validate) 27 | - [میلادی به شمسی](https://github.com/fingerpich/jalali-moment#convert-gregorian-miladi-to-jalali-shamsi-persian) 28 | - [شمسی به میلادی](https://github.com/fingerpich/jalali-moment#convert-persianjalali--shamsi-khorshidi-to-gregorian-miladi-calendar-system) 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jalali-moment", 3 | "version": "3.3.11", 4 | "description": "Manipulate and convert Jalali and Gregorian date easily", 5 | "author": { 6 | "name": "Mojtaba Zarei (Fingerpich)", 7 | "email": "zarei.bs@gmail.com" 8 | }, 9 | "license": "MIT", 10 | "keywords": [ 11 | "manipulate", 12 | "validate", 13 | "jalali", 14 | "convert", 15 | "miladi", 16 | "shamsi", 17 | "typescript", 18 | "javascript", 19 | "persian", 20 | "khorshidi", 21 | "date", 22 | "time", 23 | "calendar" 24 | ], 25 | "main": "jalali-moment.js", 26 | "scripts": { 27 | "report-coverage": "export CODACY_PROJECT_TOKEN=7f46b99d0c1e4e0e9f176d98d70f972c; istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage && rm -rf ./coverage", 28 | "test": "mocha --reporter spec --ui bdd --colors --check-leaks test.js", 29 | "build": "webpack --config webpack.browser.js", 30 | "dev": "webpack --progress --colors --watch", 31 | "make-npm-pack": "mkdir -p pkg;cp * ./pkg;cp -r node_modules/ ./pkg/node_modules; cp npmdoc.md ./pkg/README.md; cd ./pkg;npm run build", 32 | "publish-npm-pack": "npm publish pkg;rm -rf pkg", 33 | "lint": "eslint jalali-moment.js && eslint test.js" 34 | }, 35 | "homepage": "https://github.com/fingerpich/jalali-moment", 36 | "bugs": { 37 | "url": "https://github.com/fingerpich/jalali-moment/issues" 38 | }, 39 | "repository": { 40 | "type": "git", 41 | "url": "git://github.com/fingerpich/jalali-moment.git" 42 | }, 43 | "bin": { 44 | "jalalim": "./cli.js" 45 | }, 46 | "devDependencies": { 47 | "chai": "^4.2.0", 48 | "codacy-coverage": "^3.4.0", 49 | "eslint": "^7.2.0", 50 | "istanbul": "^0.4.5", 51 | "mocha": "^8.0.1", 52 | "mocha-lcov-reporter": "^1.3.0", 53 | "uglifyjs-webpack-plugin": "^2.1.1", 54 | "webpack": "^5.15.0", 55 | "webpack-cli": "^4.3.1" 56 | }, 57 | "dependencies": { 58 | "commander": "^7.0.0", 59 | "inquirer": "^8.0.0", 60 | "moment": "^2.26.0" 61 | }, 62 | "typings": "./jalali-moment.d.ts" 63 | } 64 | -------------------------------------------------------------------------------- /npmdoc.md: -------------------------------------------------------------------------------- 1 | # Jalali Moment 2 | 3 | Display, parse, manipulate and validate jalali (Persian, Khorshidi, Shamsi) or Gregorian (Miladi) dates and times and also 4 | convert Jalali (Persian, Khorshidi, Shamsi) date to Gregorian (Miladi) or vice versa in javascript or typescript. [DEMO](https://fingerpich.github.io/jalali-moment) 5 | 6 | Read this in [فارسی](./README.fa.md) 7 | 8 | [![MIT License][license-image]][license-url] 9 | [![Build Status][travis-image]][travis-url] 10 | [![NPM version][npm-version-image]][npm-url] 11 | [![Package Quality][packageQuality-image]][packageQuality-url] 12 | [![dependencies Quality][dependencies-quality]][dependencies-quality-url] 13 | [![dev dependencies Quality][dev-dependencies-quality]][dev-dependencies-quality-url] 14 | [![Codacy Badge][codacy-quality]][codacy-quality-url] 15 | [![Codacy Badge][codacy-coverage]][codacy-coverage-url] 16 | 17 | ## How to 18 | - [Install](https://github.com/fingerpich/jalali-moment#install) 19 | - Use jalali moment in 20 | - [Node.js](https://github.com/fingerpich/jalali-moment#using-in-nodejs) 21 | - [Es5](https://github.com/fingerpich/jalali-moment#es5) 22 | - [React](https://github.com/fingerpich/jalali-moment#react) 23 | - [Typescript](https://github.com/fingerpich/jalali-moment#typescript) 24 | - [Angular](https://github.com/fingerpich/jalali-moment#angular) 25 | - [Aurelia](https://github.com/fingerpich/jalali-moment#aurelia) 26 | - [Vue](https://github.com/fingerpich/jalali-moment#vue) 27 | - [Terminal(Command Line)](https://github.com/fingerpich/jalali-moment#command-line) 28 | - [Jquery](https://github.com/fingerpich/jalali-moment#jquery) 29 | - [Plunker](https://github.com/fingerpich/jalali-moment#using-in-plunker) 30 | - [Use API](https://github.com/fingerpich/jalali-moment#api) 31 | 32 | This plugin provides using jalali and gregorian calendar system together 33 | on [momentjs](https://momentjs.com/docs/) api. 34 | 35 | ```.locale('fa');``` it will use jalali calendar system 36 | 37 | ```.locale('any other locale');``` it will use gregorian calendar system 38 | 39 | #### Usage 40 | 41 | - [Parse](https://github.com/fingerpich/jalali-moment#parse) 42 | ```js 43 | // parse gregorian date 44 | m = moment('1989/1/24', 'YYYY/M/D');// parse a gregorian (miladi) date 45 | m = moment.from('01/1989/24', 'en', 'MM/YYYY/DD'); 46 | 47 | // parse jalali date 48 | m = moment('1367/11/04', 'jYYYY/jMM/jDD'); 49 | m = moment.from('1367/04/11', 'fa', 'YYYY/MM/DD'); 50 | m = moment.from('04/1367/11', 'fa', 'DD/YYYY/MM'); 51 | ``` 52 | - [Display](https://github.com/fingerpich/jalali-moment#display-jalali-or-miladi-date) 53 | ```js 54 | m.format('jYYYY/jMM/jDD'); // 1367/11/04 55 | m.locale('fa').format('YYYY/MM/DD'); // 1367/11/04 56 | ``` 57 | - [Manipulate](https://github.com/fingerpich/jalali-moment#manipulate) 58 | ```js 59 | m.add(1, 'day').locale('fa').format('YYYY/MM/DD'); // 1367/11/05 60 | ``` 61 | - [Validate](https://github.com/fingerpich/jalali-moment#validate) 62 | ```js 63 | m.isSame(m.clone()); // true 64 | ``` 65 | - [Convert](https://github.com/fingerpich/jalali-moment#convert-persianjalali--shamsi-khorshidi-to-gregorian-miladi-calendar-system) 66 | ```js 67 | moment.from('1367/11/04', 'fa', 'YYYY/MM/DD').format('YYYY/MM/DD'); // 1989/01/24 68 | moment('1989/01/24', 'YYYY/MM/DD').locale('fa').format('YYYY/MM/DD'); // 1367/11/04 69 | ``` 70 | 71 | 72 | [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat 73 | [license-url]: LICENSE 74 | 75 | [npm-url]: https://npmjs.org/package/jalali-moment 76 | [npm-version-image]: http://img.shields.io/npm/v/jalali-moment.svg?style=flat 77 | 78 | [travis-url]: https://travis-ci.org/fingerpich/jalali-moment 79 | [travis-image]: https://travis-ci.org/fingerpich/jalali-moment.png?branch=master 80 | 81 | [packageQuality-image]: http://npm.packagequality.com/shield/jalali-moment.svg 82 | [packageQuality-url]: http://packagequality.com/#?package=jalali-moment 83 | 84 | [dependencies-quality]: https://david-dm.org/fingerpich/jalali-moment.svg 85 | [dependencies-quality-url]: https://david-dm.org/fingerpich/jalali-moment 86 | 87 | [dev-dependencies-quality]: https://david-dm.org/fingerpich/jalali-moment/dev-status.svg 88 | [dev-dependencies-quality-url]: https://david-dm.org/fingerpich/jalali-moment?type=dev 89 | 90 | [codacy-quality]:https://api.codacy.com/project/badge/Grade/1aa5b7aadfc24238bdf825d58cb2cba1 91 | [codacy-quality-url]:https://www.codacy.com/app/zarei-bs/jalali-moment?utm_source=github.com&utm_medium=referral&utm_content=fingerpich/jalali-moment&utm_campaign=Badge_Grade 92 | 93 | [codacy-coverage]:https://api.codacy.com/project/badge/Coverage/1aa5b7aadfc24238bdf825d58cb2cba1 94 | [codacy-coverage-url]:https://www.codacy.com/app/zarei-bs/jalali-moment?utm_source=github.com&utm_medium=referral&utm_content=fingerpich/jalali-moment&utm_campaign=Badge_Coverage 95 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | تاریخ شمسی در جاوااسکریپت 6 | 7 | 8 | 9 | 10 | 11 | 57 | 58 | 59 | 60 | 61 |
62 |

تاریخ شمسی با کتابخانه Jalali Moment

63 |

64 | این پلاگین برای سهولت هرچه بیشتر در کار با تاریخ شمسی در جاوااسکریپت js یا تایپ اسکریپت ts ایجاد شده است همچنین اگر میخواهید یک تقویم میلادی را به تقویم شمسی تبدیل کنید این کتابخانه مناسب ترین گزینه است. 65 |

66 |
67 |
68 | 96 |
97 |
98 |

Miladi to Shamsi(تبدیل تاریخ میلادی به شمسی)

99 |

این کتابخانه میتواند برای تبدیل تاریخ میلادی به شمسی استفاده شود.

100 |
101 | 102 | 103 | 104 |
105 | moment(input, 'YYYY/MM/DD').locale('fa').format('YYYY/MM/DD'); 106 | 107 |
108 | 109 |
110 |

Shamsi to Miladi (تبدیل تاریخ شمسی به میلادی)

111 |

این کتابخانه میتواند برای تبدیل تاریخ شمسی به میلادی استفاده شود.

112 |
113 | 114 | 115 | 116 |
117 | moment.from(input, 'fa', 'YYYY/MM/DD').locale('en').format('YYYY/MM/DD'); 118 |
119 | 120 |
121 |

Validate shamsi date(تعیین صحت تاریخ شمسی)

122 |

این کتابخانه برای تشخیص صحت یک تاریخ شمسی یا میلادی و همچنین مقایسه بین تاریخ ها کمک میکند.

123 |
124 | 125 | 126 | 127 |
128 | moment(input, 'YYYY/MM/DD').isValid(); 129 |
130 |
131 | 132 | 140 |
141 | 142 | 143 | 144 | 145 | 146 | 147 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jalali Moment 2 | 3 | Display, parse, manipulate and validate jalali (Persian, Khorshidi, Shamsi) or Gregorian (Miladi) dates and times and also 4 | convert Jalali (Persian, Khorshidi, Shamsi) date to Gregorian (Miladi) or vice versa in javascript or typescript. [DEMO](https://fingerpich.github.io/jalali-moment) 5 | 6 | Read this in other languages: [فارسی](./README.fa.md) 7 | 8 | It was a fork of [moment-jalali](https://github.com/jalaali/moment-jalaali) but the main goal of this repository is to facilitate converting any library using [moment.js](https://momentjs.com/) to be compatible with jalali calendar system. 9 | [List of packages](https://www.npmjs.com/browse/depended/jalali-moment) use [jalali-moment](https://github.com/fingerpich/jalali-moment) to convert calendar system. 10 | 11 | [![MIT License][license-image]][license-url] 12 | [![Build Status][travis-image]][travis-url] 13 | [![NPM version][npm-version-image]][npm-url] 14 | [![Package Quality][packageQuality-image]][packageQuality-url] 15 | [![dependencies Quality][dependencies-quality]][dependencies-quality-url] 16 | [![dev dependencies Quality][dev-dependencies-quality]][dev-dependencies-quality-url] 17 | [![Codacy Badge][codacy-quality]][codacy-quality-url] 18 | [![Codacy Badge][codacy-coverage]][codacy-coverage-url] 19 | 20 | > Please take a look at [day.js](https://github.com/iamkun/dayjs), [jalaliday](https://github.com/alibaba-aero/jalaliday) module. 21 | 22 | ## How to 23 | - [Install](#install) 24 | - Use jalali moment in 25 | - [Node.js](#using-in-nodejs) 26 | - [React](#react) 27 | - [Es5](#es5) 28 | - [Typescript](#typescript) 29 | - [Angular](#angular) 30 | - [Aurelia](#aurelia) 31 | - [Vue](#vue) 32 | - [Terminal(Command Line)](#command-line) 33 | - [Jquery](#jquery) 34 | - [Plunker](#using-in-plunker) 35 | - [Use API](#api) 36 | 37 | This plugin provides using jalali and gregorian calendar system together 38 | on [momentjs](https://momentjs.com/docs/) api. 39 | 40 | ```.locale('fa');``` it will use jalali calendar system 41 | 42 | ```.locale('any other locale');``` it will use gregorian calendar system 43 | 44 | You can set locale for a moment instance(locally) or set it globally 45 | example of changing locale locally 46 | ```javascript 47 | const m = moment(); 48 | m.locale('fa'); 49 | m.format('YY-MM-DD'); // it would be in jalali system 50 | ``` 51 | change locale globally 52 | ```javascript 53 | moment.locale('fa'); 54 | moment().format();// it would be in jalali system 55 | moment().add(1,'m').format();// it would be in jalali system 56 | ``` 57 | **Notice** : When you need parse a date which is not in the system you have set for global locale you can use of method ```moment.from(date, 'another locale')``` 58 | ```javascript 59 | moment.locale('fa'); 60 | moment.from('2018-04-04', 'en', 'YYYY-MM-DD').format();// it would be in jalali system 61 | ``` 62 | When locale is globally set to 'fa', it's also possible to use gregorian calendar for parsing a date. 63 | By setting `{ useGregorianParser: true }` as second parameter of `.locale()` you can reach this. 64 | `useGregorianParser` default value is `false` in `'fa'` locale. 65 | ```javascript 66 | moment.locale('fa', { useGregorianParser: true }); 67 | moment('2018-04-04').format();// it would be in jalali system 68 | moment('2019-01-17T08:19:19.975Z').format();// it would be in jalali system 69 | ``` 70 | 71 | #### Usage 72 | 73 | - [Parse](#parse) 74 | ```js 75 | // parse gregorian date 76 | m = moment('1989/1/24', 'YYYY/M/D');// parse a gregorian (miladi) date 77 | m = moment.from('01/1989/24', 'en', 'MM/YYYY/DD'); 78 | 79 | // parse jalali date 80 | m = moment('1367/11/04', 'jYYYY/jMM/jDD'); 81 | m = moment.from('1367/04/11', 'fa', 'YYYY/MM/DD'); 82 | m = moment.from('04/1367/11', 'fa', 'DD/YYYY/MM'); 83 | ``` 84 | - [Display](#display-jalali-or-miladi-date) 85 | ```js 86 | m.format('jYYYY/jMM/jDD'); // 1367/11/04 87 | m.locale('fa').format('YYYY/MM/DD'); // 1367/11/04 88 | ``` 89 | - [Manipulate](#manipulate) 90 | ```js 91 | m.add(1, 'day').locale('fa').format('YYYY/MM/DD'); // 1367/11/05 92 | ``` 93 | - [Validate](#validate) 94 | ```js 95 | m.isSame(m.clone()); // true 96 | ``` 97 | - [Convert](#convert-persianjalali--shamsi-khorshidi-to-gregorian-miladi-calendar-system) 98 | ```js 99 | moment.from('1367/11/04', 'fa', 'YYYY/MM/DD').format('YYYY/MM/DD'); // 1989/01/24 100 | moment('1989/01/24', 'YYYY/MM/DD').locale('fa').format('YYYY/MM/DD'); // 1367/11/04 101 | ``` 102 | 103 | ## Introduction 104 | 105 | jalali(Persian) calendar is a solar calendar system. It gains approximately 1 day on the Julian calendar every 128 years. [Read more on Wikipedia](http://en.wikipedia.org/wiki/Jalali_calendar). 106 | 107 | Calendar conversion is based on the [algorithm provided by Kazimierz M. Borkowski](http://www.astro.uni.torun.pl/~kb/Papers/EMP/PersianC-EMP.htm) and has a very good performance. 108 | 109 | This plugin adds Jalali (Persian, Khorshidi, Shamsi) calendar system to [moment.js](http://momentjs.com) library. 110 | 111 | ## Install 112 | 113 | Install via **npm** 114 | ```shell 115 | npm install jalali-moment -S 116 | ``` 117 | Install via **yarn** 118 | ```shell 119 | yarn add jalali-moment 120 | ``` 121 | Install via **bower** 122 | ```shell 123 | bower install jalali-moment --save 124 | ``` 125 | 126 | ## Using in Node.js 127 | 128 | Install it via npm or yarn then use it as the following code 129 | 130 | ```js 131 | var moment = require('jalali-moment'); 132 | moment().locale('fa').format('YYYY/M/D'); 133 | ``` 134 | 135 | ## Using in browser 136 | 137 | #### ES5 138 | 139 | get library using bower, npm, cdn, or cloning the repository 140 | 141 | ```HTML 142 | 143 | 144 | 145 | 146 | 147 | 150 | ``` 151 | 152 | #### React 153 | ```js 154 | import moment from 'jalali-moment' 155 | ... 156 | render() { 157 | return ( 158 |
159 | { 160 | this.props.data.map((post,key) => 161 |
162 |

{post.title}

163 |

{moment(post.date, 'YYYY/MM/DD').locale('fa').format('YYYY/MM/DD')}

164 |
165 |
166 | )} 167 |
168 | ); 169 | } 170 | 171 | ``` 172 | 173 | #### Typescript 174 | 175 | ```ts 176 | import * as moment from 'jalali-moment'; 177 | let todayJalali = moment().locale('fa').format('YYYY/M/D'); 178 | ``` 179 | 180 | #### Angular 181 | 182 | ```ts 183 | import * as moment from 'jalali-moment'; 184 | ``` 185 | Add a pipe 186 | ```ts 187 | @Pipe({ 188 | name: 'jalali' 189 | }) 190 | export class JalaliPipe implements PipeTransform { 191 | transform(value: any, args?: any): any { 192 | let MomentDate = moment(value, 'YYYY/MM/DD'); 193 | return MomentDate.locale('fa').format('YYYY/M/D'); 194 | } 195 | } 196 | ``` 197 | and use it in component template 198 | ```HTML 199 |
{{ loadedData.date | jalali }}
200 | ``` 201 | 202 | #### Aurelia 203 | 204 | You can create a value converters like following: 205 | 206 | ``` typescript 207 | import { valueConverter } from 'aurelia-framework'; 208 | var moment = require('jalali-moment'); 209 | 210 | 211 | @valueConverter('date') 212 | export class DateValueConverter { 213 | toView(value: string, format: string = 'YYYY/MM/DD', locale: string = 'en') { 214 | if (!value) return null; 215 | return moment(value, 'YYYY/MM/DD').locale(locale).format(format); 216 | } 217 | } 218 | ``` 219 | 220 | then use this value converter in your ```html``` files: 221 | 222 | ```html 223 | 224 | 225 |

226 | 227 | ${myDate|date:myFormat:options.locale} 228 | 229 |

230 | ``` 231 | 232 | also, for aurelia developers, there is a plugin, [aurelia-time](https://github.com/shahabganji/aurelia-time), in which there are value converters for jalali-moment and other time and date libraries. 233 | 234 | #### Vue 235 | 236 | Use [vue-jalali-moment](https://github.com/fingerpich/vue-jalali-moment) library 237 | 238 | ```html 239 | {{ someDate | moment('dddd, MMMM Do YYYY') }} 240 | ``` 241 | 242 | #### Command Line 243 | 244 | Its cli needs to get installed globally 245 | 246 | ```npm i -g jalali-moment``` 247 | 248 | Then you will be able to convert Persian date to Gregorian and vice versa in terminal or command line as the following 249 | 250 | ``` 251 | jalalim tojalali 1989/1/24 252 | jalalim togregorian 1392/5/8 253 | ``` 254 | 255 | If you want something faster, checkout https://github.com/NightMachinary/jalalicli: 256 | ``` 257 | ❯ hyperfine --warmup 5 'jalalicli tojalali 2001/09/11' 'jalalim tojalali 2001/09/11' 258 | Benchmark #1: jalalicli tojalali 2001/09/11 259 | Time (mean ± σ): 4.4 ms ± 13.3 ms [User: 2.8 ms, System: 2.8 ms] 260 | Range (min … max): 0.0 ms … 107.0 ms 97 runs 261 | 262 | Benchmark #2: jalalim tojalali 2001/09/11 263 | Time (mean ± σ): 148.9 ms ± 76.5 ms [User: 88.5 ms, System: 19.4 ms] 264 | Range (min … max): 96.9 ms … 343.0 ms 21 runs 265 | 266 | Summary 267 | 'jalalicli tojalali 2001/09/11' ran 268 | 33.88 ± 103.80 times faster than 'jalalim tojalali 2001/09/11' 269 | ``` 270 | 271 | #### Jquery 272 | 273 | get library using bower, npm, cdn, or cloning the repository 274 | 275 | ```HTML 276 | 277 | 278 | 279 | 280 | 281 | 284 | ``` 285 | 286 | ## API 287 | 288 | This plugin tries to change calendar system [moment.js](https://momentjs.com/) api by using locale method. 289 | 290 | ```js 291 | now = moment(); //get the current date and time, 292 | ``` 293 | 294 | #### Parse 295 | 296 | Create a instance of moment from a Jalali (Persian) or Miladi date and time as string.[more](https://momentjs.com/docs/#/parsing/) 297 | ###### gregorian date 298 | ```js 299 | m = moment('1989/1/24', 'YYYY/M/D'); 300 | m = moment.from('1989/1/24', 'en', 'YYYY/M/D'); 301 | m = moment.from('01/1989/24', 'en', 'MM/YYYY/DD'); 302 | ``` 303 | 304 | ###### persian date 305 | ```js 306 | m = moment('1367/11/4', 'jYYYY/jM/jD'); 307 | m = moment.from('1367/11/04', 'fa', 'YYYY/MM/DD'); 308 | m = moment.from('11/1367/04', 'fa', 'MM/YYYY/DD'); 309 | 310 | // it will change locale for all new moment instance 311 | moment.locale('fa'); 312 | m = moment('1367/11/04', 'YYYY/M/D'); 313 | ``` 314 | 315 | #### Display jalali or miladi date 316 | 317 | Display moment instance as a string.[more](https://momentjs.com/docs/#/displaying/) 318 | ```js 319 | moment.locale('en'); // default locale is en 320 | m = moment('1989/1/24', 'YYYY/M/D'); 321 | m.locale('fa'); // change locale for this moment instance 322 | m.format('YYYY/M/D');// 1367/11/4 323 | m.format('MM'); // 11 display jalali month 324 | m.format('MMMM'); // Bahman 325 | m.format('DD'); // 04 display day by two digit 326 | m.format('DDD'); // 310 display day of year 327 | m.format('w'); // 45 display week of year 328 | m.locale('en'); 329 | m.format('M'); // 1 display miladi month 330 | m.format('MM'); // 01 display month by two digit 331 | m.format('MMMM'); // January 332 | m.format('jYYYY/jM/jD [is] YYYY/M/D'); // 1367/11/4 is 1989/1/24 333 | ``` 334 | 335 | #### Manipulate 336 | 337 | There are a number of methods to modify date and time.[more](https://momentjs.com/docs/#/manipulating/) 338 | ```js 339 | m.locale('fa'); 340 | m.year(1368); // set jalali year 341 | // If the range is exceeded, it will bubble up to the year. 342 | m.month(3); // month will be 4 and m.format('M')=='4' , jMonth Accepts numbers from 0 to 11. 343 | m.date(10); // set a date 344 | m.format('YYYY/MM/D'); // 1368/4/10 345 | m.subtract(1, 'year'); // subtract a Jalali Year 346 | m.format('YYYY/MM/D'); // 1367/4/10 347 | m.add(2, 'month'); // add two shamsi Month 348 | m.format('YYYY/MM/D'); // 1367/6/10 349 | m.endOf('month').format('YYYY/MM/D'); // 1367/6/31 350 | m.startOf('year').format('YYYY/MM/D'); // 1367/1/1 351 | ``` 352 | 353 | #### Validate 354 | 355 | Check a date and time.[more](https://momentjs.com/docs/#/query/) 356 | ```js 357 | m = moment('1367/11/4', 'jYYYY/jM/jD'); 358 | m.locale('fa'); 359 | m.isLeapYear(); // false 360 | m.isSame(moment('1989-01-01','YYYY-MM-DD'), 'year'); // true 361 | m.isSame(moment('1367-01-01','jYYYY-jMM-jDD'), 'year'); // true 362 | m.isBefore(moment('1367-01-01','jYYYY-jMM-jDD'), 'month'); // false 363 | m.isAfter(moment('1367-01-01','jYYYY-jMM-jDD'), 'jyear'); // false 364 | m.isValid(); // true 365 | moment('1396/7/31' ,'jYYYY/jM/jD').isValid(); // false 366 | ``` 367 | [validation demo in plunker](https://plnkr.co/caWsmd) 368 | 369 | #### Convert persian(Jalali , Shamsi, khorshidi) to gregorian (miladi) calendar system 370 | ```js 371 | moment.from('1392/6/3 16:40', 'fa', 'YYYY/M/D HH:mm') 372 | .format('YYYY-M-D HH:mm:ss'); // 2013-8-25 16:40:00 373 | ``` 374 | 375 | #### Convert gregorian (miladi) to jalali (Shamsi, persian) 376 | ```js 377 | moment('2013-8-25 16:40:00', 'YYYY-M-D HH:mm:ss') 378 | .locale('fa') 379 | .format('YYYY/M/D HH:mm:ss'); // 1392/6/31 23:59:59 380 | ``` 381 | 382 | ### Change calendar system on changing its locale 383 | ```js 384 | moment.bindCalendarSystemAndLocale(); 385 | ``` 386 | 387 | ### An example usage: 388 | To make a datePicker work with jalali(shamsi) calendar system you could use this ability. 389 | 390 | ## Using in Plunker 391 | 392 | #### ES5 393 | 394 | ```HTML 395 | 396 | 399 | ``` 400 | [es5 demo in plunker](https://plnkr.co/caWsmd) 401 | 402 | #### Typescript or es6 403 | 404 | You could use systemjs to import this library into your project like [this](https://embed.plnkr.co/Gggh1u/) 405 | 406 | ## Related Projects 407 | 408 | #### jalali-angular-datepicker ( angular2 or more) 409 | 410 | A highly configurable date picker built for Angular 4 or Angular 2 applications using `jalali-moment` is [fingerpich/jalali-angular-datepicker](https://github.com/fingerpich/jalali-angular-datepicker) created by [@Fingerpich](https://github.com/fingerpich). 411 | 412 | #### jalaali-moment 413 | 414 | A Jalaali calendar system plugin for moment.js is [jalaali-moment](https://github.com/jalaali/moment-jalaali). 415 | 416 | #### aurelia-time 417 | 418 | [aurelia-time](https://github.com/shahabganji/aurelia-time) Contains a set of value converters for [Aurelia](http://aurelia.io), one which uses jalali-moment. 419 | 420 | [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat 421 | [license-url]: LICENSE 422 | 423 | [npm-url]: https://npmjs.org/package/jalali-moment 424 | [npm-version-image]: http://img.shields.io/npm/v/jalali-moment.svg?style=flat 425 | 426 | [travis-url]: https://travis-ci.org/fingerpich/jalali-moment 427 | [travis-image]: https://travis-ci.org/fingerpich/jalali-moment.png?branch=master 428 | 429 | [packageQuality-image]: http://npm.packagequality.com/shield/jalali-moment.svg 430 | [packageQuality-url]: http://packagequality.com/#?package=jalali-moment 431 | 432 | [dependencies-quality]: https://david-dm.org/fingerpich/jalali-moment.svg 433 | [dependencies-quality-url]: https://david-dm.org/fingerpich/jalali-moment 434 | 435 | [dev-dependencies-quality]: https://david-dm.org/fingerpich/jalali-moment/dev-status.svg 436 | [dev-dependencies-quality-url]: https://david-dm.org/fingerpich/jalali-moment?type=dev 437 | 438 | [codacy-quality]:https://api.codacy.com/project/badge/Grade/1aa5b7aadfc24238bdf825d58cb2cba1 439 | [codacy-quality-url]:https://www.codacy.com/app/zarei-bs/jalali-moment?utm_source=github.com&utm_medium=referral&utm_content=fingerpich/jalali-moment&utm_campaign=Badge_Grade 440 | 441 | [codacy-coverage]:https://api.codacy.com/project/badge/Coverage/1aa5b7aadfc24238bdf825d58cb2cba1 442 | [codacy-coverage-url]:https://www.codacy.com/app/zarei-bs/jalali-moment?utm_source=github.com&utm_medium=referral&utm_content=fingerpich/jalali-moment&utm_campaign=Badge_Coverage 443 | -------------------------------------------------------------------------------- /jalali-moment.d.ts: -------------------------------------------------------------------------------- 1 | declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, strict?: boolean): moment.Moment; 2 | declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, language?: string, strict?: boolean): moment.Moment; 3 | 4 | declare namespace moment { 5 | type RelativeTimeKey = 's' | 'm' | 'mm' | 'h' | 'hh' | 'd' | 'dd' | 'M' | 'MM' | 'y' | 'yy'; 6 | type CalendarKey = 'sameDay' | 'nextDay' | 'lastDay' | 'nextWeek' | 'lastWeek' | 'sameElse' | string; 7 | type LongDateFormatKey = 'LTS' | 'LT' | 'L' | 'LL' | 'LLL' | 'LLLL' | 'lts' | 'lt' | 'l' | 'll' | 'lll' | 'llll'; 8 | 9 | interface Locale { 10 | calendar(key?: CalendarKey, m?: Moment, now?: Moment): string; 11 | 12 | longDateFormat(key: LongDateFormatKey): string; 13 | invalidDate(): string; 14 | ordinal(n: number): string; 15 | 16 | preparse(inp: string): string; 17 | postformat(inp: string): string; 18 | relativeTime(n: number, withoutSuffix: boolean, 19 | key: RelativeTimeKey, isFuture: boolean): string; 20 | pastFuture(diff: number, absRelTime: string): string; 21 | set(config: Object): void; 22 | 23 | months(): string[]; 24 | jMonths(): string[]; 25 | 26 | months(m: Moment, format?: string): string; 27 | jMonths(m: Moment): string; 28 | monthsShort(): string[]; 29 | jMonthsShort():string[]; 30 | monthsShort(m: Moment, format?: string): string; 31 | jMonthsParse(monthName: string): number; 32 | monthsParse(monthName: string, format: string, strict: boolean): number; 33 | monthsRegex(strict: boolean): RegExp; 34 | monthsShortRegex(strict: boolean): RegExp; 35 | 36 | week(m: Moment): number; 37 | firstDayOfYear(): number; 38 | firstDayOfWeek(): number; 39 | 40 | weekdays(): string[]; 41 | weekdays(m: Moment, format?: string): string; 42 | weekdaysMin(): string[]; 43 | weekdaysMin(m: Moment): string; 44 | weekdaysShort(): string[]; 45 | weekdaysShort(m: Moment): string; 46 | weekdaysParse(weekdayName: string, format: string, strict: boolean): number; 47 | weekdaysRegex(strict: boolean): RegExp; 48 | weekdaysShortRegex(strict: boolean): RegExp; 49 | weekdaysMinRegex(strict: boolean): RegExp; 50 | 51 | isPM(input: string): boolean; 52 | meridiem(hour: number, minute: number, isLower: boolean): string; 53 | } 54 | 55 | interface StandaloneFormatSpec { 56 | format: string[]; 57 | standalone: string[]; 58 | isFormat?: RegExp; 59 | } 60 | 61 | interface WeekSpec { 62 | dow: number; 63 | doy: number; 64 | } 65 | 66 | type CalendarSpecVal = string | ((m?: MomentInput, now?: Moment) => string); 67 | interface CalendarSpec { 68 | sameDay?: CalendarSpecVal; 69 | nextDay?: CalendarSpecVal; 70 | lastDay?: CalendarSpecVal; 71 | nextWeek?: CalendarSpecVal; 72 | lastWeek?: CalendarSpecVal; 73 | sameElse?: CalendarSpecVal; 74 | 75 | // any additional properties might be used with moment.calendarFormat 76 | [x: string]: CalendarSpecVal | void; // undefined 77 | } 78 | 79 | type RelativeTimeSpecVal = ( 80 | string | 81 | ((n: number, withoutSuffix: boolean, 82 | key: RelativeTimeKey, isFuture: boolean) => string) 83 | ); 84 | type RelativeTimeFuturePastVal = string | ((relTime: string) => string); 85 | 86 | interface RelativeTimeSpec { 87 | future: RelativeTimeFuturePastVal; 88 | past: RelativeTimeFuturePastVal; 89 | s: RelativeTimeSpecVal; 90 | m: RelativeTimeSpecVal; 91 | mm: RelativeTimeSpecVal; 92 | h: RelativeTimeSpecVal; 93 | hh: RelativeTimeSpecVal; 94 | d: RelativeTimeSpecVal; 95 | dd: RelativeTimeSpecVal; 96 | M: RelativeTimeSpecVal; 97 | MM: RelativeTimeSpecVal; 98 | y: RelativeTimeSpecVal; 99 | yy: RelativeTimeSpecVal; 100 | } 101 | 102 | interface LongDateFormatSpec { 103 | LTS: string; 104 | LT: string; 105 | L: string; 106 | LL: string; 107 | LLL: string; 108 | LLLL: string; 109 | 110 | // lets forget for a sec that any upper/lower permutation will also work 111 | lts?: string; 112 | lt?: string; 113 | l?: string; 114 | ll?: string; 115 | lll?: string; 116 | llll?: string; 117 | } 118 | 119 | type MonthWeekdayFn = (momentToFormat: Moment, format?: string) => string; 120 | type WeekdaySimpleFn = (momentToFormat: Moment) => string; 121 | 122 | interface LocaleSpecification { 123 | useGregorianParser?: boolean; 124 | months?: string[] | StandaloneFormatSpec | MonthWeekdayFn; 125 | monthsShort?: string[] | StandaloneFormatSpec | MonthWeekdayFn; 126 | 127 | weekdays?: string[] | StandaloneFormatSpec | MonthWeekdayFn; 128 | weekdaysShort?: string[] | StandaloneFormatSpec | WeekdaySimpleFn; 129 | weekdaysMin?: string[] | StandaloneFormatSpec | WeekdaySimpleFn; 130 | 131 | meridiemParse?: RegExp; 132 | meridiem?: (hour: number, minute: number, isLower: boolean) => string; 133 | 134 | isPM?: (input: string) => boolean; 135 | 136 | longDateFormat?: LongDateFormatSpec; 137 | calendar?: CalendarSpec; 138 | relativeTime?: RelativeTimeSpec; 139 | invalidDate?: string; 140 | ordinal?: (n: number) => string; 141 | ordinalParse?: RegExp; 142 | 143 | week?: WeekSpec; 144 | 145 | // Allow anything: in general any property that is passed as locale spec is 146 | // put in the locale object so it can be used by locale functions 147 | [x: string]: any; 148 | } 149 | 150 | interface MomentObjectOutput { 151 | years: number; 152 | /* One digit */ 153 | months: number; 154 | /* Day of the month */ 155 | date: number; 156 | hours: number; 157 | minutes: number; 158 | seconds: number; 159 | milliseconds: number; 160 | } 161 | 162 | interface Duration { 163 | humanize(withSuffix?: boolean): string; 164 | 165 | abs(): Duration; 166 | 167 | as(units: unitOfTime.Base): number; 168 | get(units: unitOfTime.Base): number; 169 | 170 | milliseconds(): number; 171 | asMilliseconds(): number; 172 | 173 | seconds(): number; 174 | asSeconds(): number; 175 | 176 | minutes(): number; 177 | asMinutes(): number; 178 | 179 | hours(): number; 180 | asHours(): number; 181 | 182 | days(): number; 183 | asDays(): number; 184 | 185 | weeks(): number; 186 | asWeeks(): number; 187 | 188 | months(): number; 189 | asMonths(): number; 190 | 191 | years(): number; 192 | asYears(): number; 193 | 194 | add(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration; 195 | subtract(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration; 196 | 197 | locale(): string; 198 | locale(locale: LocaleSpecifier): Duration; 199 | localeData(): Locale; 200 | 201 | toISOString(keepTimeOffset?: boolean): string; 202 | toJSON(): string; 203 | 204 | /** 205 | * @deprecated since version 2.8.0 206 | */ 207 | lang(locale: LocaleSpecifier): Moment; 208 | /** 209 | * @deprecated since version 2.8.0 210 | */ 211 | lang(): Locale; 212 | /** 213 | * @deprecated 214 | */ 215 | toIsoString(): string; 216 | } 217 | 218 | interface MomentRelativeTime { 219 | future: any; 220 | past: any; 221 | s: any; 222 | m: any; 223 | mm: any; 224 | h: any; 225 | hh: any; 226 | d: any; 227 | dd: any; 228 | M: any; 229 | MM: any; 230 | y: any; 231 | yy: any; 232 | } 233 | 234 | interface MomentLongDateFormat { 235 | L: string; 236 | LL: string; 237 | LLL: string; 238 | LLLL: string; 239 | LT: string; 240 | LTS: string; 241 | 242 | l?: string; 243 | ll?: string; 244 | lll?: string; 245 | llll?: string; 246 | lt?: string; 247 | lts?: string; 248 | } 249 | 250 | interface MomentParsingFlags { 251 | empty: boolean; 252 | unusedTokens: string[]; 253 | unusedInput: string[]; 254 | overflow: number; 255 | charsLeftOver: number; 256 | nullInput: boolean; 257 | invalidMonth: string | void; // null 258 | invalidFormat: boolean; 259 | userInvalidated: boolean; 260 | iso: boolean; 261 | parsedDateParts: any[]; 262 | meridiem: string | void; // null 263 | } 264 | 265 | interface MomentParsingFlagsOpt { 266 | empty?: boolean; 267 | unusedTokens?: string[]; 268 | unusedInput?: string[]; 269 | overflow?: number; 270 | charsLeftOver?: number; 271 | nullInput?: boolean; 272 | invalidMonth?: string; 273 | invalidFormat?: boolean; 274 | userInvalidated?: boolean; 275 | iso?: boolean; 276 | parsedDateParts?: any[]; 277 | meridiem?: string; 278 | } 279 | 280 | interface MomentBuiltinFormat { 281 | __momentBuiltinFormatBrand: any; 282 | } 283 | 284 | type MomentFormatSpecification = string | MomentBuiltinFormat | (string | MomentBuiltinFormat)[]; 285 | 286 | namespace unitOfTime { 287 | type Base = ( 288 | "year" | "years" | "y" | "jYear" | 289 | "month" | "months" | "M" | "jMonth" | "jmonth" | 290 | "week" | "weeks" | "w" | "jw" | 291 | "day" | "days" | "d" | "jDay" | "jD" | 292 | "hour" | "hours" | "h" | 293 | "minute" | "minutes" | "m" | 294 | "second" | "seconds" | "s" | 295 | "millisecond" | "milliseconds" | "ms" 296 | ); 297 | 298 | type _quarter = "quarter" | "quarters" | "Q"; 299 | type _isoWeek = "isoWeek" | "isoWeeks" | "W"; 300 | type _date = "date" | "dates" | "D"; 301 | type DurationConstructor = Base | _quarter; 302 | 303 | type DurationAs = Base; 304 | 305 | type StartOf = Base | _quarter | _isoWeek | _date; 306 | 307 | type Diff = Base | _quarter; 308 | 309 | type MomentConstructor = Base | _date; 310 | 311 | type All = Base | _quarter | _isoWeek | _date | 312 | "weekYear" | "weekYears" | "gg" | 313 | "isoWeekYear" | "isoWeekYears" | "GG" | 314 | "dayOfYear" | "dayOfYears" | "DDD" | 315 | "weekday" | "weekdays" | "e" | 316 | "isoWeekday" | "isoWeekdays" | "E"; 317 | } 318 | 319 | interface MomentInputObject { 320 | years?: number; 321 | year?: number; 322 | y?: number; 323 | 324 | months?: number; 325 | month?: number; 326 | M?: number; 327 | 328 | days?: number; 329 | day?: number; 330 | d?: number; 331 | 332 | dates?: number; 333 | date?: number; 334 | D?: number; 335 | 336 | hours?: number; 337 | hour?: number; 338 | h?: number; 339 | 340 | minutes?: number; 341 | minute?: number; 342 | m?: number; 343 | 344 | seconds?: number; 345 | second?: number; 346 | s?: number; 347 | 348 | milliseconds?: number; 349 | millisecond?: number; 350 | ms?: number; 351 | } 352 | 353 | interface DurationInputObject extends MomentInputObject { 354 | quarters?: number; 355 | quarter?: number; 356 | Q?: number; 357 | 358 | weeks?: number; 359 | week?: number; 360 | w?: number; 361 | } 362 | 363 | interface MomentSetObject extends MomentInputObject { 364 | weekYears?: number; 365 | weekYear?: number; 366 | gg?: number; 367 | 368 | isoWeekYears?: number; 369 | isoWeekYear?: number; 370 | GG?: number; 371 | 372 | quarters?: number; 373 | quarter?: number; 374 | Q?: number; 375 | 376 | weeks?: number; 377 | week?: number; 378 | w?: number; 379 | 380 | isoWeeks?: number; 381 | isoWeek?: number; 382 | W?: number; 383 | 384 | dayOfYears?: number; 385 | dayOfYear?: number; 386 | DDD?: number; 387 | 388 | weekdays?: number; 389 | weekday?: number; 390 | e?: number; 391 | 392 | isoWeekdays?: number; 393 | isoWeekday?: number; 394 | E?: number; 395 | } 396 | 397 | interface FromTo { 398 | from: MomentInput; 399 | to: MomentInput; 400 | } 401 | 402 | type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined 403 | type DurationInputArg1 = Duration | number | string | FromTo | DurationInputObject | void; // null | undefined 404 | type DurationInputArg2 = unitOfTime.DurationConstructor; 405 | type LocaleSpecifier = string | Moment | Duration | string[] | boolean; 406 | 407 | interface MomentCreationData { 408 | input: MomentInput; 409 | format?: MomentFormatSpecification; 410 | locale: Locale; 411 | isUTC: boolean; 412 | strict?: boolean; 413 | } 414 | 415 | interface Moment extends Object{ 416 | format(format?: string): string; 417 | 418 | startOf(unitOfTime: unitOfTime.StartOf): Moment; 419 | endOf(unitOfTime: unitOfTime.StartOf): Moment; 420 | 421 | add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment; 422 | /** 423 | * @deprecated reverse syntax 424 | */ 425 | add(unit: unitOfTime.DurationConstructor, amount: number|string): Moment; 426 | 427 | subtract(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment; 428 | /** 429 | * @deprecated reverse syntax 430 | */ 431 | subtract(unit: unitOfTime.DurationConstructor, amount: number|string): Moment; 432 | 433 | calendar(time?: MomentInput, formats?: CalendarSpec): string; 434 | 435 | clone(): Moment; 436 | 437 | /** 438 | * @return Unix timestamp in milliseconds 439 | */ 440 | valueOf(): number; 441 | 442 | // current date/time in local mode 443 | local(keepLocalTime?: boolean): Moment; 444 | isLocal(): boolean; 445 | 446 | // current date/time in UTC mode 447 | utc(keepLocalTime?: boolean): Moment; 448 | isUTC(): boolean; 449 | /** 450 | * @deprecated use isUTC 451 | */ 452 | isUtc(): boolean; 453 | 454 | parseZone(): Moment; 455 | isValid(): boolean; 456 | invalidAt(): number; 457 | 458 | hasAlignedHourOffset(other?: MomentInput): boolean; 459 | 460 | creationData(): MomentCreationData; 461 | parsingFlags(): MomentParsingFlags; 462 | 463 | year(y: number): Moment; 464 | year(): number; 465 | jYear(y: number): Moment; 466 | jYear():number; 467 | /** 468 | * @deprecated use year(y) 469 | */ 470 | years(y: number): Moment; 471 | /** 472 | * @deprecated use year() 473 | */ 474 | years(): number; 475 | quarter(): number; 476 | quarter(q: number): Moment; 477 | quarters(): number; 478 | quarters(q: number): Moment; 479 | month(M: number|string): Moment; 480 | jMonth(M: number|string): Moment; 481 | month(): number; 482 | jMonth(): number; 483 | /** 484 | * @deprecated use month(M) 485 | */ 486 | months(M: number|string): Moment; 487 | /** 488 | * @deprecated use month() 489 | */ 490 | months(): number; 491 | day(d: number|string): Moment; 492 | day(): number; 493 | jDay(d: number|string): Moment; 494 | jDay(): number; 495 | days(d: number|string): Moment; 496 | days(): number; 497 | date(d: number): Moment; 498 | jDate(d: number): Moment; 499 | date(): number; 500 | jDate(): number; 501 | /** 502 | * @deprecated use date(d) 503 | */ 504 | dates(d: number): Moment; 505 | /** 506 | * @deprecated use jDate(d) 507 | */ 508 | jDates(d: number): Moment; 509 | /** 510 | * @deprecated use date() 511 | */ 512 | dates(): number; 513 | /** 514 | * @deprecated use jDate() 515 | */ 516 | jDates():number; 517 | 518 | hour(h: number): Moment; 519 | hour(): number; 520 | hours(h: number): Moment; 521 | hours(): number; 522 | minute(m: number): Moment; 523 | minute(): number; 524 | minutes(m: number): Moment; 525 | minutes(): number; 526 | second(s: number): Moment; 527 | second(): number; 528 | seconds(s: number): Moment; 529 | seconds(): number; 530 | millisecond(ms: number): Moment; 531 | millisecond(): number; 532 | milliseconds(ms: number): Moment; 533 | milliseconds(): number; 534 | weekday(): number; 535 | //TODO:jweekday 536 | weekday(d: number): Moment; 537 | isoWeekday(): number; 538 | isoWeekday(d: number|string): Moment; 539 | weekYear(): number; 540 | jWeekYear(): number; 541 | weekYear(d: number): Moment; 542 | jWeekYear(d: number): Moment; 543 | isoWeekYear(): number; 544 | isoWeekYear(d: number): Moment; 545 | week(): number; 546 | jWeek(): number; 547 | week(d: number): Moment; 548 | jWeek(d: number): Moment; 549 | weeks(): number; 550 | jWeeks(): number;//TODO:check it 551 | weeks(d: number): Moment; 552 | isoWeek(): number; 553 | isoWeek(d: number): Moment; 554 | isoWeeks(): number; 555 | isoWeeks(d: number): Moment; 556 | weeksInYear(): number; 557 | //TODO : jWeeksInYear 558 | isoWeeksInYear(): number; 559 | dayOfYear(): number; 560 | jDayOfYear(): number; 561 | dayOfYear(d: number): Moment; 562 | jDayOfYear(d: number): Moment; 563 | 564 | from(inp: MomentInput, suffix?: boolean): string; 565 | to(inp: MomentInput, suffix?: boolean): string; 566 | fromNow(withoutSuffix?: boolean): string; 567 | toNow(withoutPrefix?: boolean): string; 568 | 569 | diff(b: MomentInput, unitOfTime?: unitOfTime.Diff, precise?: boolean): number; 570 | 571 | toArray(): number[]; 572 | toDate(): Date; 573 | toISOString(keepTimeOffset?: boolean): string; 574 | inspect(): string; 575 | toJSON(): string; 576 | unix(): number; 577 | 578 | isLeapYear(): boolean; 579 | jIsLeapYear(): boolean; 580 | /** 581 | * @deprecated in favor of utcOffset 582 | */ 583 | zone(): number; 584 | zone(b: number|string): Moment; 585 | utcOffset(): number; 586 | utcOffset(b: number|string, keepLocalTime?: boolean): Moment; 587 | isUtcOffset(): boolean; 588 | daysInMonth(): number; 589 | jDaysInMonth(): number; 590 | isDST(): boolean; 591 | 592 | zoneAbbr(): string; 593 | zoneName(): string; 594 | 595 | isBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean; 596 | isAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean; 597 | isSame(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean; 598 | isSameOrAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean; 599 | isSameOrBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean; 600 | isBetween(a: MomentInput, b: MomentInput, granularity?: unitOfTime.StartOf, inclusivity?: "()" | "[)" | "(]" | "[]"): boolean; 601 | 602 | doAsGregorian(): Moment; 603 | 604 | /** 605 | * @deprecated as of 2.8.0, use locale 606 | */ 607 | lang(language: LocaleSpecifier): Moment; 608 | /** 609 | * @deprecated as of 2.8.0, use locale 610 | */ 611 | lang(): Locale; 612 | 613 | locale(): string; 614 | locale(locale: LocaleSpecifier): Moment; 615 | 616 | localeData(): Locale; 617 | 618 | /** 619 | * @deprecated no reliable implementation 620 | */ 621 | isDSTShifted(): boolean; 622 | 623 | // NOTE(constructor): Same as moment constructor 624 | /** 625 | * @deprecated as of 2.7.0, use moment.min/max 626 | */ 627 | max(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment; 628 | /** 629 | * @deprecated as of 2.7.0, use moment.min/max 630 | */ 631 | max(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment; 632 | 633 | // NOTE(constructor): Same as moment constructor 634 | /** 635 | * @deprecated as of 2.7.0, use moment.min/max 636 | */ 637 | min(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment; 638 | /** 639 | * @deprecated as of 2.7.0, use moment.min/max 640 | */ 641 | min(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment; 642 | 643 | get(unit: unitOfTime.All): number; 644 | set(unit: unitOfTime.All, value: number): Moment; 645 | set(objectLiteral: MomentSetObject): Moment; 646 | 647 | toObject(): MomentObjectOutput; 648 | } 649 | 650 | export var version: string; 651 | export var fn: Moment; 652 | 653 | // NOTE(constructor): Same as moment constructor 654 | export function utc(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment; 655 | export function utc(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment; 656 | 657 | export function unix(timestamp: number): Moment; 658 | 659 | export function invalid(flags?: MomentParsingFlagsOpt): Moment; 660 | export function isMoment(m: any): m is Moment; 661 | export function isDate(m: any): m is Date; 662 | export function isDuration(d: any): d is Duration; 663 | 664 | /** 665 | * @deprecated in 2.8.0 666 | */ 667 | export function lang(language?: string): string; 668 | /** 669 | * @deprecated in 2.8.0 670 | */ 671 | export function lang(language?: string, definition?: Locale): string; 672 | 673 | export function locale(language?: string): string; 674 | export function locale(language?: string[]): string; 675 | export function locale(language?: string, definition?: LocaleSpecification | void): string; // null | undefined 676 | 677 | export function localeData(key?: string | string[]): Locale; 678 | 679 | export function duration(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration; 680 | 681 | // NOTE(constructor): Same as moment constructor 682 | export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment; 683 | export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment; 684 | 685 | export function months(): string[]; 686 | export function months(index: number): string; 687 | export function months(format: string): string[]; 688 | export function months(format: string, index: number): string; 689 | export function monthsShort(): string[]; 690 | export function monthsShort(index: number): string; 691 | export function monthsShort(format: string): string[]; 692 | export function monthsShort(format: string, index: number): string; 693 | 694 | export function jWeekOfYear(mom: Moment, firstDayOfWeek: number, firstDayOfWeekOfYear: number): MomentInput; 695 | export function jDaysInMonth(jMear: number, jMonth: number): number; 696 | export function jIsLeapYear(jYear: number): boolean; 697 | export function useJalaliSystemPrimarily(): void; 698 | export function useJalaliSystemSecondary(): void; 699 | export var jConvert: any; 700 | 701 | export function from (date: string, locale: string, format?: string): Moment; 702 | 703 | export function weekdays(): string[]; 704 | export function weekdays(index: number): string; 705 | export function weekdays(format: string): string[]; 706 | export function weekdays(format: string, index: number): string; 707 | export function weekdays(localeSorted: boolean): string[]; 708 | export function weekdays(localeSorted: boolean, index: number): string; 709 | export function weekdays(localeSorted: boolean, format: string): string[]; 710 | export function weekdays(localeSorted: boolean, format: string, index: number): string; 711 | export function weekdaysShort(): string[]; 712 | export function weekdaysShort(index: number): string; 713 | export function weekdaysShort(format: string): string[]; 714 | export function weekdaysShort(format: string, index: number): string; 715 | export function weekdaysShort(localeSorted: boolean): string[]; 716 | export function weekdaysShort(localeSorted: boolean, index: number): string; 717 | export function weekdaysShort(localeSorted: boolean, format: string): string[]; 718 | export function weekdaysShort(localeSorted: boolean, format: string, index: number): string; 719 | export function weekdaysMin(): string[]; 720 | export function weekdaysMin(index: number): string; 721 | export function weekdaysMin(format: string): string[]; 722 | export function weekdaysMin(format: string, index: number): string; 723 | export function weekdaysMin(localeSorted: boolean): string[]; 724 | export function weekdaysMin(localeSorted: boolean, index: number): string; 725 | export function weekdaysMin(localeSorted: boolean, format: string): string[]; 726 | export function weekdaysMin(localeSorted: boolean, format: string, index: number): string; 727 | 728 | export function min(...moments: MomentInput[]): Moment; 729 | export function max(...moments: MomentInput[]): Moment; 730 | 731 | /** 732 | * Returns unix time in milliseconds. Overwrite for profit. 733 | */ 734 | export function now(): number; 735 | 736 | export function defineLocale(language: string, localeSpec: LocaleSpecification | void): Locale; // null 737 | export function updateLocale(language: string, localeSpec: LocaleSpecification | void): Locale; // null 738 | 739 | export function locales(): string[]; 740 | 741 | export function normalizeUnits(unit: unitOfTime.All): string; 742 | export function relativeTimeThreshold(threshold: string): number | boolean; 743 | export function relativeTimeThreshold(threshold: string, limit: number): boolean; 744 | export function relativeTimeRounding(fn: (num: number) => number): boolean; 745 | export function relativeTimeRounding(): (num: number) => number; 746 | export function calendarFormat(m: Moment, now: Moment): string; 747 | 748 | /** 749 | * Constant used to enable explicit ISO_8601 format parsing. 750 | */ 751 | export var ISO_8601: MomentBuiltinFormat; 752 | 753 | export var defaultFormat: string; 754 | export var defaultFormatUtc: string; 755 | } 756 | 757 | export = moment; 758 | -------------------------------------------------------------------------------- /jalali-moment.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = jMoment; 3 | 4 | var moment = require("moment/moment"); 5 | require("moment/locale/fa"); 6 | 7 | /************************************ 8 | Constants 9 | ************************************/ 10 | 11 | var formattingTokens = /(\[[^\[]*\])|(\\)?j(Mo|MM?M?M?|Do|DDDo|DD?D?D?|w[o|w]?|YYYYY|YYYY|YY|gg(ggg?)?|)|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g 12 | , localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g 13 | , parseTokenOneOrTwoDigits = /\d\d?/ 14 | , parseTokenOneToThreeDigits = /\d{1,3}/ 15 | , parseTokenThreeDigits = /\d{3}/ 16 | , parseTokenFourDigits = /\d{1,4}/ 17 | , parseTokenSixDigits = /[+\-]?\d{1,6}/ 18 | , parseTokenWord = /[0-9]*["a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i 19 | , parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i 20 | , parseTokenT = /T/i 21 | , parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/ 22 | 23 | , unitAliases = { 24 | jm: "jmonth" 25 | , jmonths: "jmonth" 26 | , jy: "jyear" 27 | , jyears: "jyear" 28 | } 29 | 30 | , formatFunctions = {} 31 | 32 | , ordinalizeTokens = "DDD w M D".split(" ") 33 | , paddedTokens = "M D w".split(" "); 34 | 35 | var CalendarSystems = { 36 | Jalali: 1, 37 | Gregorian: 2, 38 | } 39 | var formatTokenFunctions = { 40 | jM: function () { 41 | return this.jMonth() + 1; 42 | }, 43 | jMMM: function (format) { 44 | return this.localeData().jMonthsShort(this, format); 45 | }, 46 | jMMMM: function (format) { 47 | return this.localeData().jMonths(this, format); 48 | }, 49 | jD: function () { 50 | return this.jDate(); 51 | }, 52 | jDDD: function () { 53 | return this.jDayOfYear(); 54 | }, 55 | jw: function () { 56 | return this.jWeek(); 57 | }, 58 | jYY: function () { 59 | return leftZeroFill(this.jYear() % 100, 2); 60 | }, 61 | jYYYY: function () { 62 | return leftZeroFill(this.jYear(), 4); 63 | }, 64 | jYYYYY: function () { 65 | return leftZeroFill(this.jYear(), 5); 66 | }, 67 | jgg: function () { 68 | return leftZeroFill(this.jWeekYear() % 100, 2); 69 | }, 70 | jgggg: function () { 71 | return this.jWeekYear(); 72 | }, 73 | jggggg: function () { 74 | return leftZeroFill(this.jWeekYear(), 5); 75 | } 76 | }; 77 | 78 | function padToken(func, count) { 79 | return function (a) { 80 | return leftZeroFill(func.call(this, a), count); 81 | }; 82 | } 83 | function ordinalizeToken(func, period) { 84 | return function (a) { 85 | return this.localeData().ordinal(func.call(this, a), period); 86 | }; 87 | } 88 | 89 | (function () { 90 | var i; 91 | while (ordinalizeTokens.length) { 92 | i = ordinalizeTokens.pop(); 93 | formatTokenFunctions["j" + i + "o"] = ordinalizeToken(formatTokenFunctions["j" + i], i); 94 | } 95 | while (paddedTokens.length) { 96 | i = paddedTokens.pop(); 97 | formatTokenFunctions["j" + i + i] = padToken(formatTokenFunctions["j" + i], 2); 98 | } 99 | formatTokenFunctions.jDDDD = padToken(formatTokenFunctions.jDDD, 3); 100 | }()); 101 | 102 | /************************************ 103 | Helpers 104 | ************************************/ 105 | 106 | function extend(a, b) { 107 | var key; 108 | for (key in b) 109 | if (b.hasOwnProperty(key)){ 110 | a[key] = b[key]; 111 | } 112 | return a; 113 | } 114 | 115 | /** 116 | * return a string which length is as much as you need 117 | * @param {number} number input 118 | * @param {number} targetLength expected length 119 | * @example leftZeroFill(5,2) => 05 120 | **/ 121 | function leftZeroFill(number, targetLength) { 122 | var output = number + ""; 123 | while (output.length < targetLength){ 124 | output = "0" + output; 125 | } 126 | return output; 127 | } 128 | 129 | /** 130 | * determine object is array or not 131 | * @param input 132 | **/ 133 | function isArray(input) { 134 | return Object.prototype.toString.call(input) === "[object Array]"; 135 | } 136 | 137 | /** 138 | * Changes any moment Gregorian format to Jalali system format 139 | * @param {string} format 140 | * @example toJalaliFormat("YYYY/MMM/DD") => "jYYYY/jMMM/jDD" 141 | **/ 142 | function toJalaliFormat(format) { 143 | for (var i = 0; i < format.length; i++) { 144 | if(!i || (format[i-1] !== "j" && format[i-1] !== format[i])) { 145 | if (format[i] === "Y" || format[i] === "M" || format[i] === "D" || format[i] === "g") { 146 | format = format.slice(0, i) + "j" + format.slice(i); 147 | } 148 | } 149 | } 150 | return format; 151 | } 152 | 153 | /** 154 | * Changes any moment Gregorian units to Jalali system units 155 | * @param {string} units 156 | * @example toJalaliUnit("YYYY/MMM/DD") => "jYYYY/jMMM/jDD" 157 | **/ 158 | function toJalaliUnit(units) { 159 | switch (units) { 160 | case "week" : return "jWeek"; 161 | case "year" : return "jYear"; 162 | case "month" : return "jMonth"; 163 | case "months" : return "jMonths"; 164 | case "monthName" : return "jMonthsShort"; 165 | case "monthsShort" : return "jMonthsShort"; 166 | } 167 | return units; 168 | } 169 | 170 | /** 171 | * normalize units to be comparable 172 | * @param {string} units 173 | **/ 174 | function normalizeUnits(units, momentObj) { 175 | if (isJalali(momentObj)) { 176 | units = toJalaliUnit(units); 177 | } 178 | if (units) { 179 | var lowered = units.toLowerCase(); 180 | if (lowered.startsWith('j')) units = unitAliases[lowered] || lowered; 181 | // TODO : add unit test 182 | if (units === "jday") units = "day"; 183 | else if (units === "jd") units = "d"; 184 | } 185 | return units; 186 | } 187 | 188 | /** 189 | * set a gregorian date to moment object 190 | * @param {string} momentInstance 191 | * @param {string} year in gregorian system 192 | * @param {string} month in gregorian system 193 | * @param {string} day in gregorian system 194 | **/ 195 | function setDate(momentInstance, year, month, day) { 196 | var d = momentInstance._d; 197 | if (momentInstance._isUTC) { 198 | /*eslint-disable new-cap*/ 199 | momentInstance._d = new Date(Date.UTC(year, month, day, 200 | d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds())); 201 | /*eslint-enable new-cap*/ 202 | } else { 203 | momentInstance._d = new Date(year, month, day, 204 | d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()); 205 | } 206 | } 207 | 208 | function objectCreate(parent) { 209 | function F() {} 210 | F.prototype = parent; 211 | return new F(); 212 | } 213 | 214 | function getPrototypeOf(object) { 215 | if (Object.getPrototypeOf){ 216 | return Object.getPrototypeOf(object); 217 | } 218 | else if ("".__proto__){ 219 | return object.__proto__; 220 | } 221 | else{ 222 | return object.constructor.prototype; 223 | } 224 | } 225 | 226 | /************************************ 227 | Languages 228 | ************************************/ 229 | extend(getPrototypeOf(moment.localeData()), 230 | { _jMonths: [ "Farvardin" 231 | , "Ordibehesht" 232 | , "Khordaad" 233 | , "Tir" 234 | , "Mordaad" 235 | , "Shahrivar" 236 | , "Mehr" 237 | , "Aabaan" 238 | , "Aazar" 239 | , "Dey" 240 | , "Bahman" 241 | , "Esfand" 242 | ] 243 | , jMonths: function (m) { 244 | if (m) { 245 | return this._jMonths[m.jMonth()]; 246 | } else { 247 | return this._jMonths; 248 | } 249 | } 250 | 251 | , _jMonthsShort: [ "Far" 252 | , "Ord" 253 | , "Kho" 254 | , "Tir" 255 | , "Amo" 256 | , "Sha" 257 | , "Meh" 258 | , "Aab" 259 | , "Aaz" 260 | , "Dey" 261 | , "Bah" 262 | , "Esf" 263 | ] 264 | , jMonthsShort: function (m) { 265 | if (m) { 266 | return this._jMonthsShort[m.jMonth()]; 267 | } else { 268 | return this._jMonthsShort; 269 | } 270 | } 271 | 272 | , jMonthsParse: function (monthName) { 273 | var i 274 | , mom 275 | , regex; 276 | if (!this._jMonthsParse){ 277 | this._jMonthsParse = []; 278 | } 279 | for (i = 0; i < 12; i += 1) { 280 | // Make the regex if we don"t have it already. 281 | if (!this._jMonthsParse[i]) { 282 | mom = jMoment([2000, (2 + i) % 12, 25]); 283 | regex = "^" + this.jMonths(mom, "") + "|^" + this.jMonthsShort(mom, ""); 284 | this._jMonthsParse[i] = new RegExp(regex.replace(".", ""), "i"); 285 | } 286 | // Test the regex. 287 | if (this._jMonthsParse[i].test(monthName)){ 288 | return i; 289 | } 290 | } 291 | } 292 | } 293 | ); 294 | 295 | /************************************ 296 | Formatting 297 | ************************************/ 298 | 299 | function makeFormatFunction(format) { 300 | var array = format.match(formattingTokens) 301 | , length = array.length 302 | , i; 303 | 304 | for (i = 0; i < length; i += 1){ 305 | if (formatTokenFunctions[array[i]]){ 306 | array[i] = formatTokenFunctions[array[i]]; 307 | } 308 | } 309 | return function (mom) { 310 | var output = ""; 311 | for (i = 0; i < length; i += 1){ 312 | output += array[i] instanceof Function ? "[" + array[i].call(mom, format) + "]" : array[i]; 313 | } 314 | return output; 315 | }; 316 | } 317 | 318 | /************************************ 319 | Parsing 320 | ************************************/ 321 | 322 | function getParseRegexForToken(token, config) { 323 | switch (token) { 324 | case "jDDDD": 325 | return parseTokenThreeDigits; 326 | case "jYYYY": 327 | return parseTokenFourDigits; 328 | case "jYYYYY": 329 | return parseTokenSixDigits; 330 | case "jDDD": 331 | return parseTokenOneToThreeDigits; 332 | case "jMMM": 333 | case "jMMMM": 334 | return parseTokenWord; 335 | case "jMM": 336 | case "jDD": 337 | case "jYY": 338 | case "jM": 339 | case "jD": 340 | return parseTokenOneOrTwoDigits; 341 | case "DDDD": 342 | return parseTokenThreeDigits; 343 | case "YYYY": 344 | return parseTokenFourDigits; 345 | case "YYYYY": 346 | return parseTokenSixDigits; 347 | case "S": 348 | case "SS": 349 | case "SSS": 350 | case "DDD": 351 | return parseTokenOneToThreeDigits; 352 | case "MMM": 353 | case "MMMM": 354 | case "dd": 355 | case "ddd": 356 | case "dddd": 357 | return parseTokenWord; 358 | case "a": 359 | case "A": 360 | return moment.localeData(config._l)._meridiemParse; 361 | case "X": 362 | return parseTokenTimestampMs; 363 | case "Z": 364 | case "ZZ": 365 | return parseTokenTimezone; 366 | case "T": 367 | return parseTokenT; 368 | case "MM": 369 | case "DD": 370 | case "YY": 371 | case "HH": 372 | case "hh": 373 | case "mm": 374 | case "ss": 375 | case "M": 376 | case "D": 377 | case "d": 378 | case "H": 379 | case "h": 380 | case "m": 381 | case "s": 382 | return parseTokenOneOrTwoDigits; 383 | default: 384 | return new RegExp(token.replace("\\", "")); 385 | } 386 | } 387 | function isNull(variable) { 388 | return variable === null || variable === undefined; 389 | } 390 | function addTimeToArrayFromToken(token, input, config) { 391 | var a 392 | , datePartArray = config._a; 393 | 394 | switch (token) { 395 | case "jM": 396 | case "jMM": 397 | datePartArray[1] = isNull(input)? 0 : ~~input - 1; 398 | break; 399 | case "jMMM": 400 | case "jMMMM": 401 | a = moment.localeData(config._l).jMonthsParse(input); 402 | if (!isNull(a)){ 403 | datePartArray[1] = a; 404 | } 405 | else{ 406 | config._isValid = false; 407 | } 408 | break; 409 | case "jD": 410 | case "jDD": 411 | case "jDDD": 412 | case "jDDDD": 413 | if (!isNull(input)){ 414 | datePartArray[2] = ~~input; 415 | } 416 | break; 417 | case "jYY": 418 | datePartArray[0] = ~~input + (~~input > 47 ? 1300 : 1400); 419 | break; 420 | case "jYYYY": 421 | case "jYYYYY": 422 | datePartArray[0] = ~~input; 423 | } 424 | if (isNull(input)) { 425 | config._isValid = false; 426 | } 427 | } 428 | 429 | function dateFromArray(config) { 430 | var g 431 | , j 432 | , jy = config._a[0] 433 | , jm = config._a[1] 434 | , jd = config._a[2]; 435 | 436 | if (isNull(jy) && isNull(jm) && isNull(jd)){ 437 | return; 438 | } 439 | jy = !isNull(jy) ? jy : 0; 440 | jm = !isNull(jm) ? jm : 0; 441 | jd = !isNull(jd) ? jd : 1; 442 | if (jd < 1 || jd > jMoment.jDaysInMonth(jy, jm) || jm < 0 || jm > 11){ 443 | config._isValid = false; 444 | } 445 | g = toGregorian(jy, jm, jd); 446 | j = toJalali(g.gy, g.gm, g.gd); 447 | config._jDiff = 0; 448 | if (~~j.jy !== jy){ 449 | config._jDiff += 1; 450 | } 451 | if (~~j.jm !== jm){ 452 | config._jDiff += 1; 453 | } 454 | if (~~j.jd !== jd){ 455 | config._jDiff += 1; 456 | } 457 | return [g.gy, g.gm, g.gd]; 458 | } 459 | 460 | function makeDateFromStringAndFormat(config) { 461 | var tokens = config._f.match(formattingTokens) 462 | , string = config._i + "" 463 | , len = tokens.length 464 | , i 465 | , token 466 | , parsedInput; 467 | 468 | config._a = []; 469 | 470 | for (i = 0; i < len; i += 1) { 471 | token = tokens[i]; 472 | parsedInput = (getParseRegexForToken(token, config).exec(string) || [])[0]; 473 | if (parsedInput){ 474 | string = string.slice(string.indexOf(parsedInput) + parsedInput.length); 475 | } 476 | if (formatTokenFunctions[token]){ 477 | addTimeToArrayFromToken(token, parsedInput, config); 478 | } 479 | } 480 | if (string){ 481 | config._il = string; 482 | } 483 | return dateFromArray(config); 484 | } 485 | 486 | function makeDateFromStringAndArray(config, utc) { 487 | var len = config._f.length 488 | , i 489 | , format 490 | , tempMoment 491 | , bestMoment 492 | , currentScore 493 | , scoreToBeat; 494 | 495 | if (len === 0) { 496 | return makeMoment(new Date(NaN)); 497 | } 498 | 499 | for (i = 0; i < len; i += 1) { 500 | format = config._f[i]; 501 | currentScore = 0; 502 | tempMoment = makeMoment(config._i, format, config._l, config._strict, utc); 503 | 504 | if (!tempMoment.isValid()){ 505 | continue; 506 | } 507 | 508 | // currentScore = compareArrays(tempMoment._a, tempMoment.toArray()) 509 | currentScore += tempMoment._jDiff; 510 | if (tempMoment._il){ 511 | currentScore += tempMoment._il.length; 512 | } 513 | if (isNull(scoreToBeat) || currentScore < scoreToBeat) { 514 | scoreToBeat = currentScore; 515 | bestMoment = tempMoment; 516 | } 517 | } 518 | 519 | return bestMoment; 520 | } 521 | 522 | function removeParsedTokens(config) { 523 | var string = config._i + "" 524 | , input = "" 525 | , format = "" 526 | , array = config._f.match(formattingTokens) 527 | , len = array.length 528 | , i 529 | , match 530 | , parsed; 531 | 532 | for (i = 0; i < len; i += 1) { 533 | match = array[i]; 534 | parsed = (getParseRegexForToken(match, config).exec(string) || [])[0]; 535 | if (parsed){ 536 | string = string.slice(string.indexOf(parsed) + parsed.length); 537 | } 538 | if (!(formatTokenFunctions[match] instanceof Function)) { 539 | format += match; 540 | if (parsed){ 541 | input += parsed; 542 | } 543 | } 544 | } 545 | config._i = input; 546 | config._f = format; 547 | } 548 | 549 | /************************************ 550 | Week of Year 551 | ************************************/ 552 | 553 | function jWeekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { 554 | var end = firstDayOfWeekOfYear - firstDayOfWeek 555 | , daysToDayOfWeek = firstDayOfWeekOfYear - mom.day() 556 | , adjustedMoment; 557 | 558 | if (daysToDayOfWeek > end) { 559 | daysToDayOfWeek -= 7; 560 | } 561 | if (daysToDayOfWeek < end - 7) { 562 | daysToDayOfWeek += 7; 563 | } 564 | adjustedMoment = jMoment(mom).add(daysToDayOfWeek, "d"); 565 | return { week: Math.ceil(adjustedMoment.jDayOfYear() / 7) 566 | , year: adjustedMoment.jYear() 567 | }; 568 | } 569 | 570 | /************************************ 571 | Top Level Functions 572 | ************************************/ 573 | function isJalali (momentObj) { 574 | return momentObj && 575 | (momentObj.calSystem === CalendarSystems.Jalali) || 576 | (moment.justUseJalali && momentObj.calSystem !== CalendarSystems.Gregorian); 577 | } 578 | function isInputJalali(format, momentObj, input) { 579 | return (moment.justUseJalali || (momentObj && momentObj.calSystem === CalendarSystems.Jalali)) 580 | } 581 | function makeMoment(input, format, lang, strict, utc) { 582 | if (typeof lang === "boolean") { 583 | utc = utc || strict; 584 | strict = lang; 585 | lang = undefined; 586 | } 587 | if (moment.ISO_8601 === format) { 588 | format = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; 589 | } 590 | const inputIsJalali = isInputJalali(format, this, input); 591 | // var itsJalaliDate = (isJalali(this)); 592 | if(input && (typeof input === "string") && !format && inputIsJalali && !moment.useGregorianParser) { 593 | input = input.replace(/\//g,"-"); 594 | if(/\d{4}\-\d{2}\-\d{2}/.test(input)) { 595 | format = "jYYYY-jMM-jDD"; 596 | } else if (/\d{4}\-\d{2}\-\d{1}/.test(input)) { 597 | format = "jYYYY-jMM-jD"; 598 | } else if (/\d{4}\-\d{1}\-\d{1}/.test(input)) { 599 | format = "jYYYY-jM-jD"; 600 | } else if (/\d{4}\-\d{1}\-\d{2}/.test(input)) { 601 | format = "jYYYY-jM-jDD"; 602 | } else if (/\d{4}\-W\d{2}\-\d{2}/.test(input)) { 603 | format = "jYYYY-jW-jDD"; 604 | } else if (/\d{4}\-\d{3}/.test(input)) { 605 | format = "jYYYY-jDDD"; 606 | } else if (/\d{8}/.test(input)) { 607 | format = "jYYYYjMMjDD"; 608 | } else if (/\d{4}W\d{2}\d{1}/.test(input)) { 609 | format = "jYYYYjWWjD"; 610 | } else if (/\d{4}W\d{2}/.test(input)) { 611 | format = "jYYYYjWW"; 612 | } else if (/\d{4}\d{3}/.test(input)) { 613 | format = "jYYYYjDDD"; 614 | } 615 | } 616 | if (format && inputIsJalali){ 617 | format = toJalaliFormat(format); 618 | } 619 | if (format && typeof format === "string"){ 620 | format = fixFormat(format, moment); 621 | } 622 | 623 | var config = 624 | { _i: input 625 | , _f: format 626 | , _l: lang 627 | , _strict: strict 628 | , _isUTC: utc 629 | } 630 | , date 631 | , m 632 | , jm 633 | , origInput = input 634 | , origFormat = format; 635 | if (format) { 636 | if (isArray(format)) { 637 | return makeDateFromStringAndArray(config, utc); 638 | } else { 639 | date = makeDateFromStringAndFormat(config); 640 | removeParsedTokens(config); 641 | if (date) { 642 | format = "YYYY-MM-DD-" + config._f; 643 | input = leftZeroFill(date[0], 4) + "-" 644 | + leftZeroFill(date[1] + 1, 2) + "-" 645 | + leftZeroFill(date[2], 2) + "-" 646 | + config._i; 647 | } 648 | } 649 | } 650 | if (utc){ 651 | m = moment.utc(input, format, lang, strict); 652 | } 653 | else{ 654 | m = moment(input, format, lang, strict); 655 | } 656 | if (config._isValid === false || (input && input._isAMomentObject && !input._isValid)){ 657 | m._isValid = false; 658 | } 659 | m._jDiff = config._jDiff || 0; 660 | jm = objectCreate(jMoment.fn); 661 | extend(jm, m); 662 | if (strict && jm.isValid()) { 663 | jm._isValid = jm.format(origFormat) === origInput; 664 | } 665 | if (input && input.calSystem) { 666 | jm.calSystem = input.calSystem; 667 | } 668 | return jm; 669 | } 670 | 671 | function jMoment(input, format, lang, strict) { 672 | return makeMoment(input, format, lang, strict, false); 673 | } 674 | 675 | extend(jMoment, moment); 676 | jMoment.fn = objectCreate(moment.fn); 677 | 678 | jMoment.utc = function (input, format, lang, strict) { 679 | return makeMoment(input, format, lang, strict, true); 680 | }; 681 | 682 | jMoment.unix = function (input) { 683 | return makeMoment(input * 1000); 684 | }; 685 | 686 | /************************************ 687 | jMoment Prototype 688 | ************************************/ 689 | 690 | function fixFormat(format, _moment) { 691 | var i = 5; 692 | var replace = function (input) { 693 | return _moment.localeData().longDateFormat(input) || input; 694 | }; 695 | while (i > 0 && localFormattingTokens.test(format)) { 696 | i -= 1; 697 | format = format.replace(localFormattingTokens, replace); 698 | } 699 | return format; 700 | } 701 | 702 | jMoment.fn.format = function (format) { 703 | format = format || jMoment.defaultFormat; 704 | if (format) { 705 | if (isJalali(this)) { 706 | format = toJalaliFormat(format); 707 | } 708 | format = fixFormat(format, this); 709 | 710 | if (!formatFunctions[format]) { 711 | formatFunctions[format] = makeFormatFunction(format); 712 | } 713 | format = formatFunctions[format](this); 714 | } 715 | var formatted = moment.fn.format.call(this, format); 716 | return formatted; 717 | }; 718 | 719 | jMoment.fn.year = function (input) { 720 | if (isJalali(this)) return jMoment.fn.jYear.call(this,input); 721 | else return moment.fn.year.call(this, input); 722 | }; 723 | jMoment.fn.jYear = function (input) { 724 | var lastDay 725 | , j 726 | , g; 727 | if (typeof input === "number") { 728 | j = getJalaliOf(this); 729 | lastDay = Math.min(j.jd, jMoment.jDaysInMonth(input, j.jm)); 730 | g = toGregorian(input, j.jm, lastDay); 731 | setDate(this, g.gy, g.gm, g.gd); 732 | moment.updateOffset(this); 733 | return this; 734 | } else { 735 | return getJalaliOf(this).jy; 736 | } 737 | }; 738 | 739 | jMoment.fn.month = function (input) { 740 | if (isJalali(this)) return jMoment.fn.jMonth.call(this,input); 741 | else return moment.fn.month.call(this, input); 742 | }; 743 | jMoment.fn.jMonth = function (input) { 744 | var lastDay 745 | , j 746 | , g; 747 | if (!isNull(input)) { 748 | if (typeof input === "string") { 749 | input = this.localeData().jMonthsParse(input); 750 | if (typeof input !== "number"){ 751 | return this; 752 | } 753 | } 754 | j = getJalaliOf(this); 755 | lastDay = Math.min(j.jd, jMoment.jDaysInMonth(j.jy, input)); 756 | this.jYear(j.jy + div(input, 12)); 757 | input = mod(input, 12); 758 | if (input < 0) { 759 | input += 12; 760 | this.jYear(this.jYear() - 1); 761 | } 762 | g = toGregorian(this.jYear(), input, lastDay); 763 | setDate(this, g.gy, g.gm, g.gd); 764 | moment.updateOffset(this); 765 | return this; 766 | } else { 767 | return getJalaliOf(this).jm; 768 | } 769 | }; 770 | 771 | jMoment.fn.date = function (input) { 772 | if (isJalali(this)) return jMoment.fn.jDate.call(this,input); 773 | else return moment.fn.date.call(this, input); 774 | }; 775 | function getJalaliOf (momentObj) { 776 | var d = momentObj._d; 777 | if (momentObj._isUTC) { 778 | return toJalali(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()); 779 | } else { 780 | return toJalali(d.getFullYear(), d.getMonth(), d.getDate()); 781 | } 782 | } 783 | jMoment.fn.jDate = function (input) { 784 | var j 785 | , g; 786 | if (typeof input === "number") { 787 | j = getJalaliOf(this); 788 | g = toGregorian(j.jy, j.jm, input); 789 | setDate(this, g.gy, g.gm, g.gd); 790 | moment.updateOffset(this); 791 | return this; 792 | } else { 793 | return getJalaliOf(this).jd; 794 | } 795 | }; 796 | 797 | jMoment.fn.jDay = function (input) { 798 | if (typeof input === "number") { 799 | return moment.fn.day.call(this, input - 1); 800 | } else { 801 | return (moment.fn.day.call(this) + 1) % 7; 802 | } 803 | }; 804 | jMoment.fn.diff = function (input, unitOfTime, asFloat) { 805 | //code taken and adjusted for jalali calendar from original moment diff module https://github.com/moment/moment/blob/develop/src/lib/moment/diff.js 806 | if (!isJalali(this)) 807 | return moment.fn.diff.call(this, input, unitOfTime, asFloat); 808 | 809 | var output; 810 | switch (unitOfTime) { 811 | case "year": 812 | output = monthDiff(this, input) / 12; 813 | break; 814 | case "month": 815 | output = monthDiff(this, input); 816 | break; 817 | case "quarter": 818 | output = monthDiff(this, input) / 3; 819 | break; 820 | default: 821 | output = moment.fn.diff.call(this, input, unitOfTime, asFloat); 822 | } 823 | 824 | return asFloat ? output : (output < 0 ? Math.ceil(output) || 0 : Math.floor(output)); 825 | 826 | function monthDiff(a, b) { 827 | if (a.date() < b.date()) { 828 | // end-of-month calculations work correct when the start month has more 829 | // days than the end month. 830 | return -monthDiff(b, a); 831 | } 832 | // difference in months 833 | var wholeMonthDiff = (b.jYear() - a.jYear()) * 12 + (b.jMonth() - a.jMonth()), 834 | // b is in (anchor - 1 month, anchor + 1 month) 835 | anchor = a.clone().add(wholeMonthDiff, "months"), 836 | anchor2, 837 | adjust 838 | 839 | if (b - anchor < 0) { 840 | anchor2 = a.clone().add(wholeMonthDiff - 1, "months"); 841 | // linear across the month 842 | adjust = (b - anchor) / (anchor - anchor2); 843 | } else { 844 | anchor2 = a.clone().add(wholeMonthDiff + 1, "months"); 845 | // linear across the month 846 | adjust = (b - anchor) / (anchor2 - anchor); 847 | } 848 | 849 | //check for negative zero, return zero if negative zero 850 | return -(wholeMonthDiff + adjust) || 0; 851 | } 852 | } 853 | 854 | jMoment.fn.dayOfYear = function (input) { 855 | if (isJalali(this)) return jMoment.fn.jDayOfYear.call(this,input); 856 | else return moment.fn.dayOfYear.call(this, input); 857 | }; 858 | jMoment.fn.jDayOfYear = function (input) { 859 | var dayOfYear = Math.round((jMoment(this).startOf("day") - jMoment(this).startOf("jYear")) / 864e5) + 1; 860 | return isNull(input) ? dayOfYear : this.add(input - dayOfYear, "d"); 861 | }; 862 | 863 | jMoment.fn.week = function (input) { 864 | if (isJalali(this)) return jMoment.fn.jWeek.call(this,input); 865 | else return moment.fn.week.call(this, input); 866 | }; 867 | jMoment.fn.jWeek = function (input) { 868 | var week = jWeekOfYear(this, 6, 12).week; 869 | return isNull(input) ? week : this.add((input - week) * 7, "d"); 870 | }; 871 | 872 | jMoment.fn.weekYear = function (input) { 873 | if (isJalali(this)) return jMoment.fn.jWeekYear.call(this,input); 874 | else return moment.fn.weekYear.call(this, input); 875 | }; 876 | jMoment.fn.jWeekYear = function (input) { 877 | var year = jWeekOfYear(this, 6, 12).year; 878 | return isNull(input) ? year : this.add(input - year, "jyear"); 879 | }; 880 | 881 | jMoment.fn.add = function (val, units) { 882 | var temp; 883 | if (!isNull(units) && !isNaN(+units)) { 884 | temp = val; 885 | val = units; 886 | units = temp; 887 | } 888 | units = normalizeUnits(units, this); 889 | if (units === 'jweek' || units==='isoweek') { units = 'week' } 890 | if (units === "jyear") { 891 | this.jYear(this.jYear() + val); 892 | } else if (units === "jmonth") { 893 | this.jMonth(this.jMonth() + val); 894 | } else { 895 | moment.fn.add.call(this, val, units); 896 | } 897 | return this; 898 | }; 899 | 900 | jMoment.fn.subtract = function (val, units) { 901 | var temp; 902 | if (!isNull(units) && !isNaN(+units)) { 903 | temp = val; 904 | val = units; 905 | units = temp; 906 | } 907 | units = normalizeUnits(units, this); 908 | if (units === "jyear") { 909 | this.jYear(this.jYear() - val); 910 | } else if (units === "jmonth") { 911 | this.jMonth(this.jMonth() - val); 912 | } else { 913 | moment.fn.subtract.call(this, val, units); 914 | } 915 | return this; 916 | }; 917 | 918 | jMoment.fn.startOf = function (units) { 919 | var nunit = normalizeUnits(units, this); 920 | if( nunit === "jweek"){ 921 | return this.startOf("day").subtract(this.jDay() , "day"); 922 | } 923 | if (nunit === "jyear") { 924 | this.jMonth(0); 925 | nunit = "jmonth"; 926 | } 927 | if (nunit === "jmonth") { 928 | this.jDate(1); 929 | nunit = "day"; 930 | } 931 | if (nunit === "day") { 932 | this.hours(0); 933 | this.minutes(0); 934 | this.seconds(0); 935 | this.milliseconds(0); 936 | return this; 937 | } else { 938 | return moment.fn.startOf.call(this, units); 939 | } 940 | }; 941 | 942 | jMoment.fn.endOf = function (units) { 943 | units = normalizeUnits(units, this); 944 | if (units === undefined || units === "milisecond") { 945 | return this; 946 | } 947 | return this.startOf(units).add(1, units).subtract(1, "ms"); 948 | }; 949 | 950 | jMoment.fn.isSame = function (other, units) { 951 | units = normalizeUnits(units, this); 952 | if (units === "jyear" || units === "jmonth") { 953 | return moment.fn.isSame.call(this.clone().startOf(units), other.clone().startOf(units)); 954 | } 955 | return moment.fn.isSame.call(this, other, units); 956 | }; 957 | 958 | jMoment.fn.isBefore = function (other, units) { 959 | units = normalizeUnits(units, this); 960 | if (units === "jyear" || units === "jmonth") { 961 | return moment.fn.isBefore.call(this.clone().startOf(units), other.clone().startOf(units)); 962 | } 963 | return moment.fn.isBefore.call(this, other, units); 964 | }; 965 | 966 | jMoment.fn.isAfter = function (other, units) { 967 | units = normalizeUnits(units, this); 968 | if (units === "jyear" || units === "jmonth") { 969 | return moment.fn.isAfter.call(this.clone().startOf(units), other.clone().startOf(units)); 970 | } 971 | return moment.fn.isAfter.call(this, other, units); 972 | }; 973 | 974 | jMoment.fn.clone = function () { 975 | return jMoment(this); 976 | }; 977 | 978 | jMoment.fn.doAsJalali = function () { 979 | this.calSystem = CalendarSystems.Jalali; 980 | return this; 981 | }; 982 | jMoment.fn.doAsGregorian = function () { 983 | this.calSystem = CalendarSystems.Gregorian; 984 | return this; 985 | }; 986 | 987 | jMoment.fn.jYears = jMoment.fn.jYear; 988 | jMoment.fn.jMonths = jMoment.fn.jMonth; 989 | jMoment.fn.jDates = jMoment.fn.jDate; 990 | jMoment.fn.jWeeks = jMoment.fn.jWeek; 991 | 992 | jMoment.fn.daysInMonth = function() { 993 | if (isJalali(this)) { 994 | return this.jDaysInMonth(); 995 | } 996 | return moment.fn.daysInMonth.call(this); 997 | }; 998 | jMoment.fn.jDaysInMonth = function () { 999 | var month = this.jMonth(); 1000 | var year = this.jYear(); 1001 | if (month < 6) { 1002 | return 31; 1003 | } else if (month < 11) { 1004 | return 30; 1005 | } else if (jMoment.jIsLeapYear(year)) { 1006 | return 30; 1007 | } else { 1008 | return 29; 1009 | } 1010 | }; 1011 | 1012 | jMoment.fn.isLeapYear = function() { 1013 | if (isJalali(this)) { 1014 | return this.jIsLeapYear(); 1015 | } 1016 | return moment.fn.isLeapYear.call(this); 1017 | }; 1018 | jMoment.fn.jIsLeapYear = function () { 1019 | var year = this.jYear(); 1020 | return isLeapJalaliYear(year); 1021 | }; 1022 | jMoment.fn.locale = function(locale) { 1023 | if (locale && moment.changeCalendarSystemByItsLocale) { 1024 | if (locale === "fa") { 1025 | this.doAsJalali(); 1026 | } else { 1027 | this.doAsGregorian(); 1028 | } 1029 | } 1030 | return moment.fn.locale.call(this, locale); 1031 | }; 1032 | /************************************ 1033 | jMoment Statics 1034 | ************************************/ 1035 | jMoment.locale = function(locale, options) { 1036 | if (locale && moment.changeCalendarSystemByItsLocale) { 1037 | if (locale === "fa") { 1038 | this.useJalaliSystemPrimarily(options); 1039 | } else { 1040 | this.useJalaliSystemSecondary(); 1041 | } 1042 | } 1043 | return moment.locale.call(this, locale); 1044 | }; 1045 | 1046 | jMoment.from = function(date, locale, format) { 1047 | var lastLocale = jMoment.locale(); 1048 | jMoment.locale(locale); 1049 | var m = jMoment(date, format); 1050 | m.locale(lastLocale); 1051 | jMoment.locale(lastLocale); 1052 | return m; 1053 | }; 1054 | 1055 | jMoment.bindCalendarSystemAndLocale = function () { 1056 | moment.changeCalendarSystemByItsLocale = true; 1057 | }; 1058 | jMoment.unBindCalendarSystemAndLocale = function () { 1059 | moment.changeCalendarSystemByItsLocale = false; 1060 | }; 1061 | 1062 | jMoment.useJalaliSystemPrimarily = function (options) { 1063 | moment.justUseJalali = true; 1064 | var useGregorianParser = false; 1065 | if (options) { 1066 | useGregorianParser = options.useGregorianParser; 1067 | } 1068 | moment.useGregorianParser = useGregorianParser; 1069 | }; 1070 | jMoment.useJalaliSystemSecondary = function () { 1071 | moment.justUseJalali = false; 1072 | }; 1073 | 1074 | jMoment.jDaysInMonth = function (year, month) { 1075 | year += div(month, 12); 1076 | month = mod(month, 12); 1077 | if (month < 0) { 1078 | month += 12; 1079 | year -= 1; 1080 | } 1081 | if (month < 6) { 1082 | return 31; 1083 | } else if (month < 11) { 1084 | return 30; 1085 | } else if (jMoment.jIsLeapYear(year)) { 1086 | return 30; 1087 | } else { 1088 | return 29; 1089 | } 1090 | }; 1091 | 1092 | jMoment.jIsLeapYear = isLeapJalaliYear; 1093 | 1094 | moment.updateLocale("fa", { 1095 | months: ("ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر").split("_") 1096 | , monthsShort: ("ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر").split("_") 1097 | , weekdays: ("یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه").split("_") 1098 | , weekdaysShort: ("یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه").split("_") 1099 | , weekdaysMin: "ی_د_س_چ_پ_ج_ش".split("_") 1100 | , longDateFormat: 1101 | { LT: "HH:mm" 1102 | , L: "jYYYY/jMM/jDD" 1103 | , LL: "jD jMMMM jYYYY" 1104 | , LLL: "jD jMMMM jYYYY LT" 1105 | , LLLL: "dddd، jD jMMMM jYYYY LT" 1106 | } 1107 | , calendar: 1108 | { sameDay: "[امروز ساعت] LT" 1109 | , nextDay: "[فردا ساعت] LT" 1110 | , nextWeek: "dddd [ساعت] LT" 1111 | , lastDay: "[دیروز ساعت] LT" 1112 | , lastWeek: "dddd [ی پیش ساعت] LT" 1113 | , sameElse: "L" 1114 | } 1115 | , relativeTime: 1116 | { future: "در %s" 1117 | , past: "%s پیش" 1118 | , s: "چند ثانیه" 1119 | , m: "1 دقیقه" 1120 | , mm: "%d دقیقه" 1121 | , h: "1 ساعت" 1122 | , hh: "%d ساعت" 1123 | , d: "1 روز" 1124 | , dd: "%d روز" 1125 | , M: "1 ماه" 1126 | , MM: "%d ماه" 1127 | , y: "1 سال" 1128 | , yy: "%d سال" 1129 | } 1130 | , ordinal: "%dم", 1131 | preparse: function (string) { 1132 | return string; 1133 | }, 1134 | postformat: function (string) { 1135 | return string; 1136 | } 1137 | , week: 1138 | { dow: 6 // Saturday is the first day of the week. 1139 | , doy: 12 // The week that contains Jan 1st is the first week of the year. 1140 | } 1141 | , meridiem: function (hour) { 1142 | return hour < 12 ? "ق.ظ" : "ب.ظ"; 1143 | } 1144 | , jMonths: ("فروردین_اردیبهشت_خرداد_تیر_مرداد_شهریور_مهر_آبان_آذر_دی_بهمن_اسفند").split("_") 1145 | , jMonthsShort: "فروردین_اردیبهشت_خرداد_تیر_مرداد_شهریور_مهر_آبان_آذر_دی_بهمن_اسفند".split("_") 1146 | }); 1147 | jMoment.bindCalendarSystemAndLocale(); 1148 | moment.locale("en"); 1149 | 1150 | jMoment.jConvert = { toJalali: toJalali 1151 | , toGregorian: toGregorian 1152 | }; 1153 | 1154 | /************************************ 1155 | Jalali Conversion 1156 | ************************************/ 1157 | 1158 | function toJalali(gy, gm, gd) { 1159 | var j = convertToJalali(gy, gm + 1, gd); 1160 | j.jm -= 1; 1161 | return j; 1162 | } 1163 | 1164 | function toGregorian(jy, jm, jd) { 1165 | var g = convertToGregorian(jy, jm + 1, jd); 1166 | g.gm -= 1; 1167 | return g; 1168 | } 1169 | 1170 | /* 1171 | Utility helper functions. 1172 | */ 1173 | 1174 | function div(a, b) { 1175 | return ~~(a / b); 1176 | } 1177 | 1178 | function mod(a, b) { 1179 | return a - ~~(a / b) * b; 1180 | } 1181 | 1182 | /* 1183 | Converts a Gregorian date to Jalali. 1184 | */ 1185 | function convertToJalali(gy, gm, gd) { 1186 | if (Object.prototype.toString.call(gy) === "[object Date]") { 1187 | gd = gy.getDate(); 1188 | gm = gy.getMonth() + 1; 1189 | gy = gy.getFullYear(); 1190 | } 1191 | return d2j(g2d(gy, gm, gd)); 1192 | } 1193 | 1194 | /* 1195 | Converts a Jalali date to Gregorian. 1196 | */ 1197 | function convertToGregorian(jy, jm, jd) { 1198 | return d2g(j2d(jy, jm, jd)); 1199 | } 1200 | 1201 | /* 1202 | Is this a leap year or not? 1203 | */ 1204 | function isLeapJalaliYear(jy) { 1205 | return jalCal(jy).leap === 0; 1206 | } 1207 | 1208 | /* 1209 | This function determines if the Jalali (Persian) year is 1210 | leap (366-day long) or is the common year (365 days), and 1211 | finds the day in March (Gregorian calendar) of the first 1212 | day of the Jalali year (jy). 1213 | @param jy Jalali calendar year (-61 to 3177) 1214 | @return 1215 | leap: number of years since the last leap year (0 to 4) 1216 | gy: Gregorian year of the beginning of Jalali year 1217 | march: the March day of Farvardin the 1st (1st day of jy) 1218 | @see: http://www.astro.uni.torun.pl/~kb/Papers/EMP/PersianC-EMP.htm 1219 | @see: http://www.fourmilab.ch/documents/calendar/ 1220 | */ 1221 | function jalCal(jy) { 1222 | // Jalali years starting the 33-year rule. 1223 | var breaks = [ -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210 1224 | , 1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178 1225 | ] 1226 | , bl = breaks.length 1227 | , gy = jy + 621 1228 | , leapJ = -14 1229 | , jp = breaks[0] 1230 | , jm 1231 | , jump 1232 | , leap 1233 | , leapG 1234 | , march 1235 | , n 1236 | , i; 1237 | 1238 | if (jy < jp || jy >= breaks[bl - 1]) 1239 | throw new Error("Invalid Jalali year " + jy); 1240 | 1241 | // Find the limiting years for the Jalali year jy. 1242 | for (i = 1; i < bl; i += 1) { 1243 | jm = breaks[i]; 1244 | jump = jm - jp; 1245 | if (jy < jm) 1246 | break; 1247 | leapJ = leapJ + div(jump, 33) * 8 + div(mod(jump, 33), 4); 1248 | jp = jm; 1249 | } 1250 | n = jy - jp; 1251 | 1252 | // Find the number of leap years from AD 621 to the beginning 1253 | // of the current Jalali year in the Persian calendar. 1254 | leapJ = leapJ + div(n, 33) * 8 + div(mod(n, 33) + 3, 4); 1255 | if (mod(jump, 33) === 4 && jump - n === 4) 1256 | leapJ += 1; 1257 | 1258 | // And the same in the Gregorian calendar (until the year gy). 1259 | leapG = div(gy, 4) - div((div(gy, 100) + 1) * 3, 4) - 150; 1260 | 1261 | // Determine the Gregorian date of Farvardin the 1st. 1262 | march = 20 + leapJ - leapG; 1263 | 1264 | // Find how many years have passed since the last leap year. 1265 | if (jump - n < 6) 1266 | n = n - jump + div(jump + 4, 33) * 33; 1267 | leap = mod(mod(n + 1, 33) - 1, 4); 1268 | if (leap === -1) { 1269 | leap = 4; 1270 | } 1271 | 1272 | return { leap: leap 1273 | , gy: gy 1274 | , march: march 1275 | }; 1276 | } 1277 | 1278 | /* 1279 | Converts a date of the Jalali calendar to the Julian Day number. 1280 | @param jy Jalali year (1 to 3100) 1281 | @param jm Jalali month (1 to 12) 1282 | @param jd Jalali day (1 to 29/31) 1283 | @return Julian Day number 1284 | */ 1285 | function j2d(jy, jm, jd) { 1286 | var r = jalCal(jy); 1287 | return g2d(r.gy, 3, r.march) + (jm - 1) * 31 - div(jm, 7) * (jm - 7) + jd - 1; 1288 | } 1289 | 1290 | /* 1291 | Converts the Julian Day number to a date in the Jalali calendar. 1292 | @param jdn Julian Day number 1293 | @return 1294 | jy: Jalali year (1 to 3100) 1295 | jm: Jalali month (1 to 12) 1296 | jd: Jalali day (1 to 29/31) 1297 | */ 1298 | function d2j(jdn) { 1299 | var gy = d2g(jdn).gy // Calculate Gregorian year (gy). 1300 | , jy = gy - 621 1301 | , r = jalCal(jy) 1302 | , jdn1f = g2d(gy, 3, r.march) 1303 | , jd 1304 | , jm 1305 | , k; 1306 | 1307 | // Find number of days that passed since 1 Farvardin. 1308 | k = jdn - jdn1f; 1309 | if (k >= 0) { 1310 | if (k <= 185) { 1311 | // The first 6 months. 1312 | jm = 1 + div(k, 31); 1313 | jd = mod(k, 31) + 1; 1314 | return { jy: jy 1315 | , jm: jm 1316 | , jd: jd 1317 | }; 1318 | } else { 1319 | // The remaining months. 1320 | k -= 186; 1321 | } 1322 | } else { 1323 | // Previous Jalali year. 1324 | jy -= 1; 1325 | k += 179; 1326 | if (r.leap === 1) 1327 | k += 1; 1328 | } 1329 | jm = 7 + div(k, 30); 1330 | jd = mod(k, 30) + 1; 1331 | return { jy: jy 1332 | , jm: jm 1333 | , jd: jd 1334 | }; 1335 | } 1336 | 1337 | /* 1338 | Calculates the Julian Day number from Gregorian or Julian 1339 | calendar dates. This integer number corresponds to the noon of 1340 | the date (i.e. 12 hours of Universal Time). 1341 | The procedure was tested to be good since 1 March, -100100 (of both 1342 | calendars) up to a few million years into the future. 1343 | @param gy Calendar year (years BC numbered 0, -1, -2, ...) 1344 | @param gm Calendar month (1 to 12) 1345 | @param gd Calendar day of the month (1 to 28/29/30/31) 1346 | @return Julian Day number 1347 | */ 1348 | function g2d(gy, gm, gd) { 1349 | var d = div((gy + div(gm - 8, 6) + 100100) * 1461, 4) 1350 | + div(153 * mod(gm + 9, 12) + 2, 5) 1351 | + gd - 34840408; 1352 | d = d - div(div(gy + 100100 + div(gm - 8, 6), 100) * 3, 4) + 752; 1353 | return d; 1354 | } 1355 | 1356 | /* 1357 | Calculates Gregorian and Julian calendar dates from the Julian Day number 1358 | (jdn) for the period since jdn=-34839655 (i.e. the year -100100 of both 1359 | calendars) to some millions years ahead of the present. 1360 | @param jdn Julian Day number 1361 | @return 1362 | gy: Calendar year (years BC numbered 0, -1, -2, ...) 1363 | gm: Calendar month (1 to 12) 1364 | gd: Calendar day of the month M (1 to 28/29/30/31) 1365 | */ 1366 | function d2g(jdn) { 1367 | var j 1368 | , i 1369 | , gd 1370 | , gm 1371 | , gy; 1372 | j = 4 * jdn + 139361631; 1373 | j = j + div(div(4 * jdn + 183187720, 146097) * 3, 4) * 4 - 3908; 1374 | i = div(mod(j, 1461), 4) * 5 + 308; 1375 | gd = div(mod(i, 153), 5) + 1; 1376 | gm = mod(div(i, 153), 12) + 1; 1377 | gy = div(j, 1461) - 100100 + div(8 - gm, 6); 1378 | return { gy: gy 1379 | , gm: gm 1380 | , gd: gd 1381 | }; 1382 | } 1383 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 2 | var chai = require("chai"); 3 | var jalaliMoment = require("./jalali-moment.js"); 4 | var moment = require("moment"); 5 | 6 | chai.should(); 7 | 8 | jalaliMoment.updateLocale("en" 9 | , { week: 10 | { dow: 6 11 | , doy: 12 12 | } 13 | , longDateFormat: 14 | { LT: "h:mm A" 15 | , L: "jYYYY/jMM/jDD" 16 | , LL: "jD jMMMM jYYYY" 17 | , LLL: "jD jMMMM jYYYY LT" 18 | , LLLL: "dddd, jD jMMMM jYYYY LT" 19 | } 20 | } 21 | ); 22 | 23 | describe("moment", function() { 24 | describe("#parse", function() { 25 | it("should parse gregorian dates", function() { 26 | var m = jalaliMoment("1981/8/17 07:10:20", "YYYY/M/D hh:mm:ss"); 27 | m.format("YYYY-MM-DD hh:mm:ss").should.be.equal("1981-08-17 07:10:20"); 28 | m.milliseconds().should.be.equal(0); 29 | }); 30 | it("parse persian dates", function () { 31 | jalaliMoment.locale("fa"); 32 | var m1 = jalaliMoment("1367/11/04", "YYYY/M/D"); 33 | m1.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 34 | m1 = jalaliMoment("1367/11/4", "YYYY/M/D"); 35 | m1.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 36 | m1 = jalaliMoment("1367/1/4", "YYYY/M/D"); 37 | m1.format("YYYY/MM/DD").should.be.equal("1367/01/04"); 38 | var m1 = jalaliMoment("13671124", "YYYYMMDD"); 39 | m1.format("YYYY/MM/DD").should.be.equal("1367/11/24"); 40 | // var m1 = jalaliMoment("1367/245"); 41 | // m1.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 42 | jalaliMoment.locale("en"); 43 | }); 44 | 45 | it("should parse correctly when input is only time", function() { 46 | var jm = jalaliMoment("07:10:20", "hh:mm:ss"); 47 | var m = moment("07:10:20", "hh:mm:ss"); 48 | jm.format("YYYY-MM-DD hh:mm:ss").should.be.equal(m.format("YYYY-MM-DD hh:mm:ss")) 49 | }); 50 | 51 | it("should parse when only Jalaali year is in the format", function() { 52 | var m = jalaliMoment("08 1360 17", "MM jYYYY DD"); 53 | m.format("YYYY-MM-DD").should.be.equal("1981-08-17"); 54 | m = jalaliMoment("08 60 17", "MM jYY DD"); 55 | m.format("YYYY-MM-DD").should.be.equal("1981-08-17"); 56 | }); 57 | 58 | it("should parse when only Jalaali month is in the format", function() { 59 | var m = jalaliMoment("1981 5 17", "YYYY jM D"); 60 | m.format("YYYY-MM-DD").should.be.equal("1981-07-17"); 61 | }); 62 | 63 | it("should parse when only Jalaali month string is in the format", function() { 64 | var m = jalaliMoment("1981 Amo 17", "YYYY jMMM D"); 65 | m.format("YYYY-MM-DD").should.be.equal("1981-07-17"); 66 | m = jalaliMoment("1981 Mordaad 17", "YYYY jMMMM D"); 67 | m.format("YYYY-MM-DD").should.be.equal("1981-07-17"); 68 | }); 69 | 70 | it("should parse when only Jalaali date is in the format", function() { 71 | var m = jalaliMoment("1981 26 8", "YYYY jD M"); 72 | m.format("YYYY-MM-DD").should.be.equal("1981-08-15"); 73 | }); 74 | 75 | it("should parse when Jalaali year and month are in the format", function() { 76 | var m = jalaliMoment("17 1360 5", "D jYYYY jM"); 77 | m.format("YYYY-MM-DD").should.be.equal("1981-07-17"); 78 | m = jalaliMoment("1392 7", "jYYYY jM"); 79 | m.format("YYYY-MM-DD").should.be.equal("2013-09-23"); 80 | }); 81 | 82 | it("should parse when Jalaali year and date are in the format", function() { 83 | var m = jalaliMoment("26 1360 8", "jD jYYYY M"); 84 | m.format("YYYY-MM-DD").should.be.equal("1981-08-15"); 85 | }); 86 | 87 | it("should parse when Jalaali month and date are in the format", function() { 88 | jalaliMoment.locale('en'); 89 | var m = jalaliMoment("26 1981 5", "jD YYYY jM"); 90 | m.format("YYYY-MM-DD").should.be.equal("1981-08-17"); 91 | }); 92 | 93 | it("should parse when Jalaali year, month and date are in the format", function() { 94 | var m = jalaliMoment("26 1360 5", "jD jYYYY jM"); 95 | m.format("YYYY-MM-DD").should.be.equal("1981-08-17"); 96 | }); 97 | 98 | it("should parse with complex format", function() { 99 | var m = jalaliMoment("17 26 50 1981 50 8 12", "D jD jYYYY YYYY M M jM"); 100 | m.format("YYYY-MM-DD").should.be.equal("1981-08-17"); 101 | }); 102 | 103 | it("should parse format result", function() { 104 | var f = "jYYYY/jM/jD hh:mm:ss.SSS a" 105 | , m = jalaliMoment(); 106 | jalaliMoment(m.format(f), f).isSame(m).should.be.equal(true); 107 | }); 108 | 109 | it("should be able to parse in utc", function() { 110 | var m = jalaliMoment.utc("1360/5/26 07:10:20", "jYYYY/jM/jD hh:mm:ss"); 111 | m.format("YYYY-MM-DD hh:mm:ss Z").should.be.equal("1981-08-17 07:10:20 +00:00"); 112 | }); 113 | 114 | it("should parse with a format array", function() { 115 | var p1 = "jYY jM jD" 116 | , p2 = "jM jD jYY" 117 | , p3 = "jD jYY jM" 118 | , m; 119 | m = jalaliMoment("60 11 12", ["D YY M", "M D YY", "YY M D"]); 120 | m.format("YY-MM-DD").should.be.equal("60-11-12"); 121 | m = jalaliMoment("10 11 12", [p1, p2, p3]); 122 | m.format("jYY-jMM-jDD").should.be.equal("10-11-12"); 123 | m = jalaliMoment("10 11 12", [p2, p3, p1]); 124 | m.format("jYY-jMM-jDD").should.be.equal("12-10-11"); 125 | m = jalaliMoment("10 11 12", [p3, p1, p2]); 126 | m.format("jYY-jMM-jDD").should.be.equal("11-12-10"); 127 | m = jalaliMoment("10 11 12", [p3, p2, p1]); 128 | m.format("jYY-jMM-jDD").should.be.equal("11-12-10"); 129 | m = jalaliMoment("60-11-12", [p3, p2, p1]); 130 | m.format("jYY-jMM-jDD").should.be.equal("60-11-12"); 131 | m = jalaliMoment("60 11 12", [p3, p2, p1]); 132 | m.format("jYY-jMM-jDD").should.be.equal("60-11-12"); 133 | m = jalaliMoment("60 8 31", ["YY M D", "jYY jM jD"]); 134 | m.format("YY-MM-DD").should.be.equal("60-08-31"); 135 | m = jalaliMoment("60 8 31", ["jYY jM jD", "YY M D"]); 136 | m.format("YY-MM-DD").should.be.equal("60-08-31"); 137 | m = jalaliMoment("60 5 31", ["YY M D", "jYY jM jD"]); 138 | m.format("YY-MM-DD").should.be.equal("60-05-31"); 139 | m = jalaliMoment("60 5 31", ["jYY jM jD", "YY M D"]); 140 | m.format("jYY-jMM-jDD").should.be.equal("60-05-31"); 141 | }); 142 | }); 143 | 144 | describe("#format", function() { 145 | it("should work normally when there is no Jalaali token", function() { 146 | var m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD hh:mm:ss"); 147 | m.format("YYYY-MM-DD hh:mm:ss").should.be.equal("1981-08-17 07:10:20"); 148 | }); 149 | 150 | it("should format to Jalaali with Jalaali tokens", function() { 151 | var m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD hh:mm:ss"); 152 | m.format("jYYYY-jMM-jDD hh:mm:ss").should.be.equal("1360-05-26 07:10:20"); 153 | }); 154 | 155 | it("should format with escaped and unescaped tokens", function() { 156 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 157 | m.format("[My] birt\\h [is] jYYYY or YYYY").should.be.equal("My birth is 1360 or 1981"); 158 | }); 159 | 160 | it("should format with mixed tokens", function() { 161 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 162 | m.format("jYYYY/jMM/jDD = YYYY-MM-DD").should.be.equal("1360/05/26 = 1981-08-17"); 163 | }); 164 | 165 | it("should format with jMo", function() { 166 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 167 | m.format("jMo").should.be.equal("5th"); 168 | }); 169 | 170 | it("should format with jM", function() { 171 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 172 | m.format("jM").should.be.equal("5"); 173 | }); 174 | 175 | it("should format with jMM", function() { 176 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 177 | m.format("jMM").should.be.equal("05"); 178 | }); 179 | 180 | it("should format with jMMM", function() { 181 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 182 | m.format("jMMM").should.be.equal("Amo"); 183 | }); 184 | 185 | it("should format with jMMMM", function() { 186 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 187 | m.format("jMMMM").should.be.equal("Mordaad"); 188 | }); 189 | 190 | it("should format with jDo", function() { 191 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 192 | m.format("jDo").should.be.equal("26th"); 193 | }); 194 | 195 | it("should format with jD", function() { 196 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 197 | m.format("jD").should.be.equal("26"); 198 | }); 199 | 200 | it("should format with jDD", function() { 201 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 202 | m.format("jDD").should.be.equal("26"); 203 | m = jalaliMoment("1981-08-23", "YYYY-MM-DD"); 204 | m.format("jDD").should.be.equal("01"); 205 | }); 206 | 207 | it("should format with jDDD", function() { 208 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 209 | m.format("jDDD").should.be.equal("150"); 210 | }); 211 | 212 | it("should format with jDDDo", function() { 213 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 214 | m.format("jDDDo").should.be.equal("150th"); 215 | }); 216 | 217 | it("should format with jDDDD", function() { 218 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 219 | m.format("jDDDD").should.be.equal("150"); 220 | m = jalaliMoment("1981-03-21", "YYYY-MM-DD"); 221 | m.format("jDDDD").should.be.equal("001"); 222 | }); 223 | 224 | it("should format with jwo", function() { 225 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 226 | m.format("jwo").should.be.equal("22nd"); 227 | }); 228 | 229 | it("should format with jw", function() { 230 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 231 | m.format("jw").should.be.equal("22"); 232 | }); 233 | 234 | it("should format with jww", function() { 235 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 236 | m.format("jww").should.be.equal("22"); 237 | m = jalaliMoment("1981-04-23", "YYYY-MM-DD"); 238 | m.format("jww").should.be.equal("05"); 239 | }); 240 | 241 | it("should format with jYY", function() { 242 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 243 | m.format("jYY").should.be.equal("60"); 244 | }); 245 | 246 | it("should format with jYYYY", function() { 247 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 248 | m.format("jYYYY").should.be.equal("1360"); 249 | }); 250 | 251 | it("should format with jYYYYY", function() { 252 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 253 | m.format("jYYYYY").should.be.equal("01360"); 254 | }); 255 | 256 | it("should format with jgg", function() { 257 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 258 | m.format("jgg").should.be.equal("60"); 259 | }); 260 | 261 | it("should format with jgggg", function() { 262 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 263 | m.format("jgggg").should.be.equal("1360"); 264 | }); 265 | 266 | it("should format with jggggg", function() { 267 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 268 | m.format("jggggg").should.be.equal("01360"); 269 | }); 270 | 271 | it("should work with long date formats too", function() { 272 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 273 | m.format("LT").should.be.equal("12:00 AM"); 274 | m.format("L").should.be.equal("1360/05/26"); 275 | m.format("l").should.be.equal("1360/5/26"); 276 | m.format("LL").should.be.equal("26 Mordaad 1360"); 277 | m.format("ll").should.be.equal("26 Amo 1360"); 278 | m.format("LLL").should.be.equal("26 Mordaad 1360 12:00 AM"); 279 | m.format("lll").should.be.equal("26 Amo 1360 12:00 AM"); 280 | m.format("LLLL").should.be.equal("Monday, 26 Mordaad 1360 12:00 AM"); 281 | m.format("llll").should.be.equal("Mon, 26 Amo 1360 12:00 AM"); 282 | }); 283 | 284 | it("should format another", function() { 285 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 286 | // m.format("Z").should.be.equal("+03:30"); its depend on where it executed 287 | // m.format("X").should.be.equal("366841800"); 288 | m.format("dddd").should.be.equal("Monday"); 289 | m.format("YYYYY").should.be.equal("01981"); 290 | m.format("DDDD").should.be.equal("229"); 291 | m.format("jDDD").should.be.equal("150"); 292 | m.format("jYYYYY").should.be.equal("01360"); 293 | }); 294 | }); 295 | 296 | describe("#jYear", function() { 297 | it("should return Jalaali year", function() { 298 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 299 | m.jYear().should.be.equal(1360); 300 | }); 301 | 302 | it("should set Jalaali year", function() { 303 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 304 | m.jYear(1392); 305 | m.format("jYYYY/jM/jD").should.be.equal("1392/5/26"); 306 | m = jalaliMoment("2013-03-20", "YYYY-MM-DD"); 307 | m.format("jYY/jM/jD").should.be.equal("91/12/30"); 308 | m.jYear(1392); 309 | m.format("jYY/jM/jD").should.be.equal("92/12/29"); 310 | }); 311 | 312 | it("should also has jYears alias", function() { 313 | jalaliMoment.fn.jYear.should.be.equal(jalaliMoment.fn.jYears); 314 | }); 315 | }); 316 | 317 | describe("#jMonth", function() { 318 | it("should return Jalaali month", function() { 319 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 320 | m.jMonth().should.be.equal(4); 321 | }); 322 | 323 | it("should set Jalaali month", function() { 324 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 325 | m.jMonth(7); 326 | m.format("jYYYY/jM/jD").should.be.equal("1360/8/26"); 327 | m = jalaliMoment("2012-08-21", "YYYY-MM-DD"); 328 | m.format("jYY/jM/jD").should.be.equal("91/5/31"); 329 | m.jMonth(11); 330 | m.format("jYY/jM/jD").should.be.equal("91/12/30"); 331 | m = jalaliMoment("2013-08-22"); 332 | m.format("jYY/jM/jD").should.be.equal("92/5/31"); 333 | m.jMonth(11); 334 | m.format("jYY/jM/jD").should.be.equal("92/12/29"); 335 | }); 336 | 337 | it("should also has jMonths alias", function() { 338 | jalaliMoment.fn.jMonth.should.be.equal(jalaliMoment.fn.jMonths); 339 | }); 340 | }); 341 | 342 | describe("#jDay", function() { 343 | it("should return Jalaali week day name", function() { 344 | var m = jalaliMoment("1989-01-24", "YYYY-MM-DD"); 345 | m.jDay().should.be.equal(3); 346 | }); 347 | 348 | it("should set Jalaali month", function() { 349 | var m = jalaliMoment("1989-01-24", "YYYY-MM-DD"); 350 | m.jDay(5); 351 | m.format("jYYYY/jM/jD").should.be.equal("1367/11/6"); 352 | }); 353 | }); 354 | describe("#jDaysInMonth", function() { 355 | it("should return Jalaali days count in month", function() { 356 | const md = jalaliMoment.from('1398/12/01', 'fa', 'YYYY/MM/DD').jDaysInMonth() 357 | md.should.be.equal(29); 358 | }); 359 | it("should return ordibehesht days count", function() { 360 | const md = jalaliMoment.from('1398/01/01', 'fa', 'jYYYY/jMM/jDD').jDaysInMonth(); 361 | md.should.be.equal(31); 362 | }); 363 | it("should return leap year esfand days count", function() { 364 | const md = jalaliMoment.jDaysInMonth(1398, 11); // esfand 98 365 | md.should.be.equal(29); 366 | }); 367 | }); 368 | 369 | describe("#jDate", function() { 370 | it("should return Jalaali date", function() { 371 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 372 | m.jDate().should.be.equal(26); 373 | }); 374 | 375 | it("should set Jalaali date", function() { 376 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 377 | m.jDate(30); 378 | m.format("jYYYY/jM/jD").should.be.equal("1360/5/30"); 379 | m = jalaliMoment("2013-03-01", "YYYY-MM-DD"); 380 | m.format("jYY/jM/jD").should.be.equal("91/12/11"); 381 | m.jDate(29); 382 | m.format("jYY/jM/jD").should.be.equal("91/12/29"); 383 | m.jDate(30); 384 | m.format("jYY/jM/jD").should.be.equal("91/12/30"); 385 | m.jDate(30); 386 | m.format("jYY/jM/jD").should.be.equal("91/12/30"); 387 | m.jDate(31); 388 | m.format("jYY/jM/jD").should.be.equal("92/1/1"); 389 | m.jDate(90); 390 | m.format("jYY/jM/jD").should.be.equal("92/3/28"); 391 | }); 392 | 393 | it("should also has jDates alias", function() { 394 | jalaliMoment.fn.jDate.should.be.equal(jalaliMoment.fn.jDates); 395 | }); 396 | }); 397 | 398 | describe("#jDayOfYear", function() { 399 | it("should return Jalaali date of year", function() { 400 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 401 | m.jDayOfYear().should.be.equal(150); 402 | m = jalaliMoment("1981-03-21", "YYYY-MM-DD"); 403 | m.jDayOfYear().should.be.equal(1); 404 | m = jalaliMoment("1982-03-20", "YYYY-MM-DD"); 405 | m.jDayOfYear().should.be.equal(365); 406 | m = jalaliMoment("1984-03-20", "YYYY-MM-DD"); 407 | m.jDayOfYear().should.be.equal(366); 408 | }); 409 | 410 | it("should set Jalaali date of year", function() { 411 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 412 | m.jDayOfYear(30); 413 | m.format("jYYYY/jM/jD").should.be.equal("1360/1/30"); 414 | m.jDayOfYear(364); 415 | m.format("jYY/jM/jD").should.be.equal("60/12/28"); 416 | m.jDayOfYear(365); 417 | m.format("jYY/jM/jD").should.be.equal("60/12/29"); 418 | m.jDayOfYear(366); 419 | m.format("jYY/jM/jD").should.be.equal("61/1/1"); 420 | m.jDayOfYear(1); 421 | m.format("jYY/jM/jD").should.be.equal("61/1/1"); 422 | m.jDayOfYear(90); 423 | m.format("jYY/jM/jD").should.be.equal("61/3/28"); 424 | m.jDayOfYear(365 + 366); 425 | m.format("jYY/jM/jD").should.be.equal("62/12/30"); 426 | }); 427 | }); 428 | 429 | describe("#jWeek", function() { 430 | it("jweek with both locale", function() { 431 | var m = jalaliMoment("1396/01/05","jYYYY/jMM/jDD"); 432 | jalaliMoment.locale("en"); 433 | m.locale("en"); 434 | m.format("jYY/jM/jD").should.be.equal("96/1/5"); 435 | m.jWeek().should.be.equal(2); 436 | m.locale("fa"); 437 | m.jWeek().should.be.equal(2); 438 | }); 439 | it("should return Jalaali week of year", function() { 440 | var m = jalaliMoment("1396/01/04","jYYYY/jMM/jDD"); 441 | m.format("jYY/jM/jD").should.be.equal("96/1/4"); 442 | m.jWeek().should.be.equal(1); 443 | m = jalaliMoment("1396/01/05","jYYYY/jMM/jDD"); 444 | m.format("jYY/jM/jD").should.be.equal("96/1/5"); 445 | m.jWeek().should.be.equal(2); 446 | m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 447 | m.jWeek().should.be.equal(22); 448 | m.jDayOfYear(1); 449 | m.format("jYY/jM/jD").should.be.equal("60/1/1"); 450 | m.jWeek().should.be.equal(1); 451 | m.jDayOfYear(8); 452 | m.format("jYY/jM/jD").should.be.equal("60/1/8"); 453 | m.jWeek().should.be.equal(2); 454 | m.jDayOfYear(14); 455 | m.format("jYY/jM/jD").should.be.equal("60/1/14"); 456 | m.jWeek().should.be.equal(2); 457 | m.jDayOfYear(364); 458 | m.format("jYY/jM/jD").should.be.equal("60/12/28"); 459 | m.jWeek().should.be.equal(52); 460 | m.jDayOfYear(365); 461 | m.format("jYY/jM/jD").should.be.equal("60/12/29"); 462 | m.jWeek().should.be.equal(1); 463 | m.jDayOfYear(366); 464 | m.format("jYY/jM/jD").should.be.equal("61/1/1"); 465 | m.jWeek().should.be.equal(1); 466 | m.jDayOfYear(363); 467 | m.format("jYY/jM/jD").should.be.equal("61/12/27"); 468 | m.jWeek().should.be.equal(52); 469 | m.jDayOfYear(365); 470 | m.format("jYY/jM/jD").should.be.equal("61/12/29"); 471 | m.jWeek().should.be.equal(1); 472 | m.jDayOfYear(366); 473 | m.format("jYY/jM/jD").should.be.equal("62/1/1"); 474 | m.jWeek().should.be.equal(1); 475 | m.jDayOfYear(365); 476 | m.format("jYY/jM/jD").should.be.equal("62/12/29"); 477 | m.jWeek().should.be.equal(1); 478 | m.jDayOfYear(366); 479 | m.format("jYY/jM/jD").should.be.equal("62/12/30"); 480 | m.jWeek().should.be.equal(1); 481 | m.jDayOfYear(367); 482 | m.format("jYY/jM/jD").should.be.equal("63/1/1"); 483 | m.jWeek().should.be.equal(1); 484 | m.jDayOfYear(365); 485 | m.format("jYY/jM/jD").should.be.equal("63/12/29"); 486 | m.jWeek().should.be.equal(1); 487 | m.jDayOfYear(366); 488 | m.format("jYY/jM/jD").should.be.equal("64/1/1"); 489 | m.jWeek().should.be.equal(1); 490 | m.jDayOfYear(365); 491 | m.format("jYY/jM/jD").should.be.equal("64/12/29"); 492 | m.jWeek().should.be.equal(1); 493 | m.jDayOfYear(366); 494 | m.format("jYY/jM/jD").should.be.equal("65/1/1"); 495 | m.jWeek().should.be.equal(1); 496 | m.jDayOfYear(358); 497 | m.format("jYY/jM/jD").should.be.equal("65/12/22"); 498 | m.jWeek().should.be.equal(52); 499 | m.jDayOfYear(359); 500 | m.format("jYY/jM/jD").should.be.equal("65/12/23"); 501 | m.jWeek().should.be.equal(53); 502 | m.jDayOfYear(360); 503 | m.format("jYY/jM/jD").should.be.equal("65/12/24"); 504 | m.jWeek().should.be.equal(53); 505 | m.jDayOfYear(361); 506 | m.format("jYY/jM/jD").should.be.equal("65/12/25"); 507 | m.jWeek().should.be.equal(53); 508 | m.jDayOfYear(362); 509 | m.format("jYY/jM/jD").should.be.equal("65/12/26"); 510 | m.jWeek().should.be.equal(53); 511 | m.jDayOfYear(363); 512 | m.format("jYY/jM/jD").should.be.equal("65/12/27"); 513 | m.jWeek().should.be.equal(53); 514 | m.jDayOfYear(364); 515 | m.format("jYY/jM/jD").should.be.equal("65/12/28"); 516 | m.jWeek().should.be.equal(53); 517 | m.jDayOfYear(365); 518 | m.format("jYY/jM/jD").should.be.equal("65/12/29"); 519 | m.jWeek().should.be.equal(53); 520 | }); 521 | 522 | it("should set Jalaali week of year", function() { 523 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 524 | m.jWeek(1); 525 | m.format("jYY/jM/jD").should.be.equal("60/1/3"); 526 | m.jWeek(22); 527 | m.format("jYY/jM/jD").should.be.equal("60/5/26"); 528 | m.jWeek(52); 529 | m.format("jYY/jM/jD").should.be.equal("60/12/24"); 530 | m.jWeek(53); 531 | m.format("jYY/jM/jD").should.be.equal("61/1/2"); 532 | m.jWeek(1); 533 | m.format("jYY/jM/jD").should.be.equal("61/1/2"); 534 | m.jWeek(0); 535 | m.format("jYY/jM/jD").should.be.equal("60/12/24"); 536 | m.jWeek(-1); 537 | m.format("jYY/jM/jD").should.be.equal("59/12/18"); 538 | }); 539 | }); 540 | 541 | describe("#jWeekYear", function() { 542 | it("should return Jalaali week year", function() { 543 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 544 | m.jWeekYear().should.be.equal(1360); 545 | m.jDayOfYear(1); 546 | m.format("jYY/jM/jD").should.be.equal("60/1/1"); 547 | m.jWeekYear().should.be.equal(1360); 548 | m.jDayOfYear(364); 549 | m.format("jYY/jM/jD").should.be.equal("60/12/28"); 550 | m.jWeekYear().should.be.equal(1360); 551 | m.jDayOfYear(365); 552 | m.format("jYY/jM/jD").should.be.equal("60/12/29"); 553 | m.jWeekYear().should.be.equal(1361); 554 | m.jDayOfYear(366); 555 | m.format("jYY/jM/jD").should.be.equal("61/1/1"); 556 | m.jWeekYear().should.be.equal(1361); 557 | m.jDayOfYear(363); 558 | m.format("jYY/jM/jD").should.be.equal("61/12/27"); 559 | m.jWeekYear().should.be.equal(1361); 560 | m.jDayOfYear(365); 561 | m.format("jYY/jM/jD").should.be.equal("61/12/29"); 562 | m.jWeekYear().should.be.equal(1362); 563 | m.jDayOfYear(366); 564 | m.format("jYY/jM/jD").should.be.equal("62/1/1"); 565 | m.jWeekYear().should.be.equal(1362); 566 | m.jDayOfYear(365); 567 | m.format("jYY/jM/jD").should.be.equal("62/12/29"); 568 | m.jWeekYear().should.be.equal(1363); 569 | m.jDayOfYear(366); 570 | m.format("jYY/jM/jD").should.be.equal("62/12/30"); 571 | m.jWeekYear().should.be.equal(1363); 572 | m.jDayOfYear(367); 573 | m.format("jYY/jM/jD").should.be.equal("63/1/1"); 574 | m.jWeekYear().should.be.equal(1363); 575 | m.jDayOfYear(365); 576 | m.format("jYY/jM/jD").should.be.equal("63/12/29"); 577 | m.jWeekYear().should.be.equal(1364); 578 | m.jDayOfYear(366); 579 | m.format("jYY/jM/jD").should.be.equal("64/1/1"); 580 | m.jWeekYear().should.be.equal(1364); 581 | m.jDayOfYear(365); 582 | m.format("jYY/jM/jD").should.be.equal("64/12/29"); 583 | m.jWeekYear().should.be.equal(1365); 584 | m.jDayOfYear(366); 585 | m.format("jYY/jM/jD").should.be.equal("65/1/1"); 586 | m.jWeekYear().should.be.equal(1365); 587 | m.jDayOfYear(358); 588 | m.format("jYY/jM/jD").should.be.equal("65/12/22"); 589 | m.jWeekYear().should.be.equal(1365); 590 | m.jDayOfYear(359); 591 | m.format("jYY/jM/jD").should.be.equal("65/12/23"); 592 | m.jWeekYear().should.be.equal(1365); 593 | m.jDayOfYear(365); 594 | m.format("jYY/jM/jD").should.be.equal("65/12/29"); 595 | m.jWeekYear().should.be.equal(1365); 596 | m.jDayOfYear(366); 597 | m.format("jYY/jM/jD").should.be.equal("66/1/1"); 598 | m.jWeekYear().should.be.equal(1366); 599 | }); 600 | 601 | it("should set Jalaali week year", function() { 602 | var m = jalaliMoment("1981-08-17", "YYYY-MM-DD"); 603 | m.jWeekYear(1361); 604 | m.format("jYY/jM/jD").should.be.equal("61/5/26"); 605 | m.jWeekYear(1364); 606 | m.format("jYY/jM/jD").should.be.equal("64/5/26"); 607 | m.jDayOfYear(365); 608 | m.format("jYY/jM/jD").should.be.equal("64/12/29"); 609 | m.jWeekYear(1364); 610 | m.format("jYY/jM/jD").should.be.equal("63/12/29"); 611 | m.jWeekYear(1365); 612 | m.format("jYY/jM/jD").should.be.equal("64/12/29"); 613 | }); 614 | }); 615 | 616 | describe("#startOf", function() { 617 | it("should work as expected without jYear and jMonth", function() { 618 | var m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 619 | m.startOf("year").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-01-01 00:00:00"); 620 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 621 | m.startOf("month").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-08-01 00:00:00"); 622 | m = jalaliMoment("1981-08-17 07:10:20"); 623 | m.startOf("day").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-08-17 00:00:00"); 624 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 625 | m.startOf("week").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-08-15 00:00:00"); 626 | }); 627 | 628 | it("should return start of Jalaali year, month and date", function() { 629 | var m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 630 | m.startOf("jYear").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1360-01-01 00:00:00"); 631 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 632 | m.startOf("jMonth").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1360-05-01 00:00:00"); 633 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 634 | m.startOf("day").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1360-05-26 00:00:00"); 635 | m = jalaliMoment("2017-12-14 07:10:20", "YYYY-MM-DD HH:mm:ss"); 636 | m.startOf("jweek").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1396-09-18 00:00:00"); 637 | m.locale("fa").startOf("week").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1396-09-18 00:00:00"); 638 | }); 639 | }); 640 | 641 | describe("#endOf", function() { 642 | it("should work as expected without jYear and jMonth", function() { 643 | var m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 644 | m.endOf("year").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-12-31 23:59:59"); 645 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 646 | m.endOf("month").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-08-31 23:59:59"); 647 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 648 | m.endOf("day").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-08-17 23:59:59"); 649 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 650 | m.endOf("week").format("YYYY-MM-DD HH:mm:ss").should.be.equal("1981-08-21 23:59:59"); 651 | }); 652 | 653 | it("should return end of Jalaali year, month and date", function() { 654 | var m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 655 | m.endOf("jYear").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1360-12-29 23:59:59"); 656 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 657 | m.endOf("jMonth").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1360-05-31 23:59:59"); 658 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 659 | m.endOf("day").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1360-05-26 23:59:59"); 660 | m = jalaliMoment("1981-08-17 07:10:20", "YYYY-MM-DD HH:mm:ss"); 661 | m.endOf("week").format("jYYYY-jMM-jDD HH:mm:ss").should.be.equal("1360-05-30 23:59:59"); 662 | }); 663 | it("endOf week in locale fa #109", function() { 664 | var m = jalaliMoment.from("1367/11/04", "fa", "YYYY/MM/DD"); 665 | m = m.locale('fa'); 666 | m.endOf("week").format("YYYY-MM-DD").should.be.equal(m.startOf('week').add(7, 'day').subtract(1, 'ms').format("YYYY-MM-DD")); 667 | }); 668 | }); 669 | 670 | describe("#isValid", function() { 671 | it("should return true when a valid date is parsed and false otherwise", function() { 672 | var jf = "jYYYY/jMM/jDD" 673 | , gf = "YYYY-MM-DD"; 674 | jalaliMoment("1981-08-17", gf).isValid().should.be.equal(true); 675 | jalaliMoment("1981-08-31", gf).isValid().should.be.equal(true); 676 | jalaliMoment("1981-09-31", gf).isValid().should.be.equal(false); 677 | jalaliMoment("1360 Mordaad 26", "jYYYY jMMMM jD").isValid().should.be.equal(true); 678 | jalaliMoment("1360/05/26", jf).isValid().should.be.equal(true); 679 | jalaliMoment("1360/05/31", jf).isValid().should.be.equal(true); 680 | jalaliMoment("1360/07/30", jf).isValid().should.be.equal(true); 681 | jalaliMoment("1360/07/31", jf).isValid().should.be.equal(false); 682 | jalaliMoment("1360/12/29", jf).isValid().should.be.equal(true); 683 | jalaliMoment("1360/12/30", jf).isValid().should.be.equal(false); 684 | jalaliMoment("1360/12/31", jf).isValid().should.be.equal(false); 685 | jalaliMoment("1360/13/01", jf).isValid().should.be.equal(false); 686 | jalaliMoment("1393/11/00", jf).isValid().should.be.equal(false); 687 | }); 688 | }); 689 | 690 | describe("#isValid-strict", function () { 691 | it("should return false when gregorian date is not strictly valid", function () { 692 | var gf = "YYYY-MM-DD"; 693 | jalaliMoment("1981-08-17", gf).isValid().should.be.equal(true); 694 | jalaliMoment("1981-08-31", gf).isValid().should.be.equal(true); 695 | jalaliMoment("1981-08-311", gf).isValid().should.be.equal(true); 696 | jalaliMoment("1981-08-311", gf, true).isValid().should.be.equal(false); 697 | }); 698 | 699 | it("should return false when jalaali date is not strictly valid", function () { 700 | var jf = "jYYYY/jMM/jDD"; 701 | jalaliMoment("1360/05/26", jf).isValid().should.be.equal(true); 702 | jalaliMoment("1360/05/31", jf).isValid().should.be.equal(true); 703 | jalaliMoment("1360/05/311", jf, true).isValid().should.be.equal(false); 704 | }); 705 | }); 706 | 707 | describe("#clone", function() { 708 | it("should return a cloned instance", function() { 709 | var m = jalaliMoment("1360/5/26", "jYYYY/jM/jD") 710 | , c = m.clone(); 711 | m.add(1, "jYear"); 712 | m.add(4, "day"); 713 | m.format("jYY/jM/jD").should.be.equal("61/5/30"); 714 | c.format("jYY/jM/jD").should.be.equal("60/5/26"); 715 | }); 716 | it("clone of an invalid date is invalid", function () { 717 | var m1 = jalaliMoment("hello","jYYYY/jMM/jDD"); 718 | m1.isValid().should.be.equal(false); 719 | m1.clone().isValid().should.be.equal(false); 720 | }); 721 | }); 722 | 723 | describe("#add", function () { 724 | it("should add gregorian dates correctly", function () { 725 | var gf = "YYYY-M-D" 726 | , m = jalaliMoment("1981-8-17", "YYYY-M-D"); 727 | jalaliMoment(m).add(1, "day").format(gf).should.be.equal("1981-8-18"); 728 | jalaliMoment(m).add(10, "days").format(gf).should.be.equal("1981-8-27"); 729 | jalaliMoment(m).add(30, "days").format(gf).should.be.equal("1981-9-16"); 730 | jalaliMoment(m).add(60, "days").format(gf).should.be.equal("1981-10-16"); 731 | 732 | jalaliMoment(m).add(1, "month").format(gf).should.be.equal("1981-9-17"); 733 | jalaliMoment(m).add(2, "months").format(gf).should.be.equal("1981-10-17"); 734 | jalaliMoment(m).add(10, "months").format(gf).should.be.equal("1982-6-17"); 735 | jalaliMoment(m).add(20, "months").format(gf).should.be.equal("1983-4-17"); 736 | 737 | jalaliMoment(m).add(1, "year").format(gf).should.be.equal("1982-8-17"); 738 | jalaliMoment(m).add(2, "years").format(gf).should.be.equal("1983-8-17"); 739 | jalaliMoment(m).add(10, "years").format(gf).should.be.equal("1991-8-17"); 740 | jalaliMoment(m).add(20, "years").format(gf).should.be.equal("2001-8-17"); 741 | }); 742 | 743 | it("should add jalaali dates correctly", function () { 744 | var jf = "jYYYY/jM/jD" 745 | , m = jalaliMoment("1360/5/26", "jYYYY/jM/jD"); 746 | jalaliMoment(m).add(1, "day").format(jf).should.be.equal("1360/5/27"); 747 | jalaliMoment(m).add(4, "days").format(jf).should.be.equal("1360/5/30"); 748 | jalaliMoment(m).add(10, "days").format(jf).should.be.equal("1360/6/5"); 749 | jalaliMoment(m).add(30, "days").format(jf).should.be.equal("1360/6/25"); 750 | jalaliMoment(m).add(60, "days").format(jf).should.be.equal("1360/7/24"); 751 | jalaliMoment(m).add(365, "days").format(jf).should.be.equal("1361/5/26"); 752 | 753 | jalaliMoment(m).add(1, "jmonth").format(jf).should.be.equal("1360/6/26"); 754 | jalaliMoment(m).add(2, "jmonths").format(jf).should.be.equal("1360/7/26"); 755 | jalaliMoment(m).add(10, "jmonths").format(jf).should.be.equal("1361/3/26"); 756 | jalaliMoment(m).add(20, "jmonths").format(jf).should.be.equal("1362/1/26"); 757 | 758 | jalaliMoment(m).add(1, "jyear").format(jf).should.be.equal("1361/5/26"); 759 | jalaliMoment(m).add(2, "jyears").format(jf).should.be.equal("1362/5/26"); 760 | jalaliMoment(m).add(3, "jyears").format(jf).should.be.equal("1363/5/26"); 761 | jalaliMoment(m).add(4, "jyears").format(jf).should.be.equal("1364/5/26"); 762 | jalaliMoment(m).add(10, "jyears").format(jf).should.be.equal("1370/5/26"); 763 | jalaliMoment(m).add(20, "jyears").format(jf).should.be.equal("1380/5/26"); 764 | }); 765 | 766 | it("should retain last day of month when adding months or years", function () { 767 | var jf = "jYYYY/jM/jD" 768 | , m = jalaliMoment("1393/6/31", jf); 769 | jalaliMoment(m).add(1, "jmonth").format(jf).should.be.equal("1393/7/30"); 770 | jalaliMoment(m).add(5, "jmonth").format(jf).should.be.equal("1393/11/30"); 771 | jalaliMoment(m).add(6, "jmonth").format(jf).should.be.equal("1393/12/29"); 772 | 773 | m = jalaliMoment("1391/12/30", jf); 774 | jalaliMoment(m).add(1, "jyear").format(jf).should.be.equal("1392/12/29"); 775 | jalaliMoment(m).add(2, "jyear").format(jf).should.be.equal("1393/12/29"); 776 | jalaliMoment(m).add(3, "jyear").format(jf).should.be.equal("1394/12/29"); 777 | jalaliMoment(m).add(4, "jyear").format(jf).should.be.equal("1395/12/30"); 778 | }); 779 | }); 780 | 781 | describe("#subtract", function () { 782 | it("should subtract gregorian dates correctly", function () { 783 | var gf = "YYYY-M-D" 784 | , m = jalaliMoment("1981-8-17", "YYYY-M-D"); 785 | jalaliMoment(m).subtract(1, "day").format(gf).should.be.equal("1981-8-16"); 786 | jalaliMoment(m).subtract(10, "days").format(gf).should.be.equal("1981-8-7"); 787 | jalaliMoment(m).subtract(30, "days").format(gf).should.be.equal("1981-7-18"); 788 | jalaliMoment(m).subtract(60, "days").format(gf).should.be.equal("1981-6-18"); 789 | 790 | jalaliMoment(m).subtract(1, "month").format(gf).should.be.equal("1981-7-17"); 791 | jalaliMoment(m).subtract(2, "months").format(gf).should.be.equal("1981-6-17"); 792 | jalaliMoment(m).subtract(10, "months").format(gf).should.be.equal("1980-10-17"); 793 | jalaliMoment(m).subtract(20, "months").format(gf).should.be.equal("1979-12-17"); 794 | 795 | jalaliMoment(m).subtract(1, "year").format(gf).should.be.equal("1980-8-17"); 796 | jalaliMoment(m).subtract(2, "years").format(gf).should.be.equal("1979-8-17"); 797 | jalaliMoment(m).subtract(10, "years").format(gf).should.be.equal("1971-8-17"); 798 | jalaliMoment(m).subtract(20, "years").format(gf).should.be.equal("1961-8-17"); 799 | }); 800 | 801 | it("should subtract jalaali dates correctly", function () { 802 | var jf = "jYYYY/jM/jD" 803 | , m = jalaliMoment("1360/5/26", "jYYYY/jM/jD"); 804 | jalaliMoment(m).subtract(1, "day").format(jf).should.be.equal("1360/5/25"); 805 | jalaliMoment(m).subtract(4, "days").format(jf).should.be.equal("1360/5/22"); 806 | jalaliMoment(m).subtract(10, "days").format(jf).should.be.equal("1360/5/16"); 807 | jalaliMoment(m).subtract(30, "days").format(jf).should.be.equal("1360/4/27"); 808 | jalaliMoment(m).subtract(60, "days").format(jf).should.be.equal("1360/3/28"); 809 | jalaliMoment(m).subtract(365, "days").format(jf).should.be.equal("1359/5/26"); 810 | 811 | jalaliMoment(m).subtract(1, "jmonth").format(jf).should.be.equal("1360/4/26"); 812 | jalaliMoment(m).subtract(2, "jmonths").format(jf).should.be.equal("1360/3/26"); 813 | jalaliMoment(m).subtract(10, "jmonths").format(jf).should.be.equal("1359/7/26"); 814 | jalaliMoment(m).subtract(20, "jmonths").format(jf).should.be.equal("1358/9/26"); 815 | 816 | jalaliMoment(m).subtract(1, "jyear").format(jf).should.be.equal("1359/5/26"); 817 | jalaliMoment(m).subtract(2, "jyears").format(jf).should.be.equal("1358/5/26"); 818 | jalaliMoment(m).subtract(3, "jyears").format(jf).should.be.equal("1357/5/26"); 819 | jalaliMoment(m).subtract(4, "jyears").format(jf).should.be.equal("1356/5/26"); 820 | jalaliMoment(m).subtract(10, "jyears").format(jf).should.be.equal("1350/5/26"); 821 | jalaliMoment(m).subtract(20, "jyears").format(jf).should.be.equal("1340/5/26"); 822 | }); 823 | 824 | it("should retain last day of month when subtracting months or years", function () { 825 | var jf = "jYYYY/jM/jD" 826 | , m = jalaliMoment("1393/1/31", jf); 827 | jalaliMoment(m).subtract(1, "jmonth").format(jf).should.be.equal("1392/12/29"); 828 | jalaliMoment(m).subtract(6, "jmonth").format(jf).should.be.equal("1392/7/30"); 829 | jalaliMoment(m).subtract(7, "jmonth").format(jf).should.be.equal("1392/6/31"); 830 | 831 | m = jalaliMoment("1391/12/30", jf); 832 | jalaliMoment(m).subtract(1, "jyear").format(jf).should.be.equal("1390/12/29"); 833 | jalaliMoment(m).subtract(2, "jyear").format(jf).should.be.equal("1389/12/29"); 834 | jalaliMoment(m).subtract(3, "jyear").format(jf).should.be.equal("1388/12/29"); 835 | jalaliMoment(m).subtract(4, "jyear").format(jf).should.be.equal("1387/12/30"); 836 | }); 837 | 838 | it("should subtract months correctly", function () { 839 | var jf = "jYYYY/jM/jD" 840 | , m = jalaliMoment("1393/1/31", jf); 841 | jalaliMoment(m).subtract(1, "jmonth").format(jf).should.be.equal("1392/12/29"); 842 | jalaliMoment(m).subtract(2, "jmonth").format(jf).should.be.equal("1392/11/30"); 843 | jalaliMoment(m).subtract(7, "jmonth").format(jf).should.be.equal("1392/6/31"); 844 | jalaliMoment(m).subtract(12, "jmonth").format(jf).should.be.equal("1392/1/31"); 845 | jalaliMoment(m).subtract(13, "jmonth").format(jf).should.be.equal("1391/12/30"); 846 | jalaliMoment(m).subtract(25, "jmonth").format(jf).should.be.equal("1390/12/29"); 847 | 848 | m = jalaliMoment("1393/1/1", jf); 849 | jalaliMoment(m).subtract(1, "jmonth").format(jf).should.be.equal("1392/12/1"); 850 | jalaliMoment(m).subtract(2, "jmonth").format(jf).should.be.equal("1392/11/1"); 851 | jalaliMoment(m).subtract(7, "jmonth").format(jf).should.be.equal("1392/6/1"); 852 | jalaliMoment(m).subtract(12, "jmonth").format(jf).should.be.equal("1392/1/1"); 853 | jalaliMoment(m).subtract(13, "jmonth").format(jf).should.be.equal("1391/12/1"); 854 | jalaliMoment(m).subtract(25, "jmonth").format(jf).should.be.equal("1390/12/1"); 855 | 856 | m = jalaliMoment("1393/1/10", jf); 857 | jalaliMoment(m).subtract(1, "jmonth").format(jf).should.be.equal("1392/12/10"); 858 | jalaliMoment(m).subtract(2, "jmonth").format(jf).should.be.equal("1392/11/10"); 859 | jalaliMoment(m).subtract(7, "jmonth").format(jf).should.be.equal("1392/6/10"); 860 | jalaliMoment(m).subtract(12, "jmonth").format(jf).should.be.equal("1392/1/10"); 861 | jalaliMoment(m).subtract(13, "jmonth").format(jf).should.be.equal("1391/12/10"); 862 | jalaliMoment(m).subtract(25, "jmonth").format(jf).should.be.equal("1390/12/10"); 863 | }); 864 | }); 865 | 866 | describe(".jIsLeapYear", function() { 867 | it("should return true for Jalaali leap years and false otherwise", function() { 868 | jalaliMoment.jIsLeapYear(1391).should.be.equal(true); 869 | jalaliMoment.jIsLeapYear(1392).should.be.equal(false); 870 | jalaliMoment.jIsLeapYear(1393).should.be.equal(false); 871 | jalaliMoment.jIsLeapYear(1394).should.be.equal(false); 872 | jalaliMoment.jIsLeapYear(1395).should.be.equal(true); 873 | jalaliMoment.jIsLeapYear(1396).should.be.equal(false); 874 | jalaliMoment.jIsLeapYear(1397).should.be.equal(false); 875 | jalaliMoment.jIsLeapYear(1398).should.be.equal(false); 876 | jalaliMoment.jIsLeapYear(1399).should.be.equal(true); 877 | jalaliMoment.jIsLeapYear(1400).should.be.equal(false); 878 | jalaliMoment.jIsLeapYear(1401).should.be.equal(false); 879 | jalaliMoment.jIsLeapYear(1402).should.be.equal(false); 880 | jalaliMoment.jIsLeapYear(1403).should.be.equal(true); 881 | jalaliMoment.jIsLeapYear(1404).should.be.equal(false); 882 | }); 883 | }); 884 | 885 | describe(".unix", function () { 886 | it("should create a jalaliMoment with unix epoch", function () { 887 | var unix = jalaliMoment("1360/5/26", "jYYYY/jM/jD").unix(); 888 | jalaliMoment.unix(unix).format("jYYYY/jM/jD").should.be.equal("1360/5/26"); 889 | }); 890 | }); 891 | describe("#isSame", function () { 892 | it("should work correctly for same year", function () { 893 | var m1 = jalaliMoment("2016-02-04", "YYYY-MM-DD"); 894 | var m2 = jalaliMoment("2016-01-01", "YYYY-MM-DD"); 895 | var m3 = jalaliMoment("2015-12-31", "YYYY-MM-DD"); 896 | var m4 = jalaliMoment("2017-01-01", "YYYY-MM-DD"); 897 | m1.isSame(m2, "year").should.be.equal(true); 898 | m1.isSame(m3, "year").should.be.equal(false); 899 | m1.isSame(m4, "year").should.be.equal(false); 900 | m2.isSame(m3, "year").should.be.equal(false); 901 | m2.isSame(m4, "year").should.be.equal(false); 902 | m3.isSame(m4, "year").should.be.equal(false); 903 | m1.isSame(jalaliMoment("2016-02-04", "YYYY-MM-DD"), "day").should.be.equal(true); 904 | }); 905 | 906 | it("should work correctly for same month", function () { 907 | var m1 = jalaliMoment("2016-02-04", "YYYY-MM-DD"); 908 | var m2 = jalaliMoment("2016-02-01", "YYYY-MM-DD"); 909 | var m3 = jalaliMoment("2016-01-01", "YYYY-MM-DD"); 910 | var m4 = jalaliMoment("2016-03-01", "YYYY-MM-DD"); 911 | m1.isSame(m2, "month").should.be.equal(true); 912 | m1.isSame(m3, "month").should.be.equal(false); 913 | m1.isSame(m4, "month").should.be.equal(false); 914 | m2.isSame(m3, "month").should.be.equal(false); 915 | m2.isSame(m4, "month").should.be.equal(false); 916 | m3.isSame(m4, "month").should.be.equal(false); 917 | m1.isSame(jalaliMoment("2016-02-04", "YYYY-MM-DD"), "day").should.be.equal(true); 918 | }); 919 | 920 | it("should work correctly for same day", function () { 921 | var m1 = jalaliMoment("2016-02-04 06:00", "YYYY-MM-DD HH:mm"); 922 | var m2 = jalaliMoment("2016-02-04 07:00", "YYYY-MM-DD HH:mm"); 923 | var m3 = jalaliMoment("2016-02-03 06:00", "YYYY-MM-DD HH:mm"); 924 | var m4 = jalaliMoment("2016-02-05 06:00", "YYYY-MM-DD HH:mm"); 925 | m1.isSame(m2, "day").should.be.equal(true); 926 | m1.isSame(m3, "day").should.be.equal(false); 927 | m1.isSame(m4, "day").should.be.equal(false); 928 | m2.isSame(m3, "day").should.be.equal(false); 929 | m2.isSame(m4, "day").should.be.equal(false); 930 | m3.isSame(m4, "day").should.be.equal(false); 931 | }); 932 | 933 | it("should work correctly for same jyear", function () { 934 | var m1 = jalaliMoment("1394/11/15", "jYYYY/jMM/jDD"); 935 | var m2 = jalaliMoment("1394/01/01", "jYYYY/jMM/jDD"); 936 | var m3 = jalaliMoment("1393/11/15", "jYYYY/jMM/jDD"); 937 | var m4 = jalaliMoment("1395/11/15", "jYYYY/jMM/jDD"); 938 | m1.isSame(m2, "jyear").should.be.equal(true); 939 | m1.isSame(m3, "jyear").should.be.equal(false); 940 | m1.isSame(m4, "jyear").should.be.equal(false); 941 | m2.isSame(m3, "jyear").should.be.equal(false); 942 | m2.isSame(m4, "jyear").should.be.equal(false); 943 | m3.isSame(m4, "jyear").should.be.equal(false); 944 | }); 945 | 946 | it("should work correctly for same jmonth", function () { 947 | var m1 = jalaliMoment("1394/11/15", "jYYYY/jMM/jDD"); 948 | var m2 = jalaliMoment("1394/11/01", "jYYYY/jMM/jDD"); 949 | var m3 = jalaliMoment("1394/10/15", "jYYYY/jMM/jDD"); 950 | var m4 = jalaliMoment("1394/12/15", "jYYYY/jMM/jDD"); 951 | m1.isSame(m2, "jmonth").should.be.equal(true); 952 | m1.isSame(m3, "jmonth").should.be.equal(false); 953 | m1.isSame(m4, "jmonth").should.be.equal(false); 954 | m2.isSame(m3, "jmonth").should.be.equal(false); 955 | m2.isSame(m4, "jmonth").should.be.equal(false); 956 | m3.isSame(m4, "jmonth").should.be.equal(false); 957 | }); 958 | it("it absolutely should work correctly for same jday", function () { 959 | var m1 = jalaliMoment("2016-02-04 06:00", "YYYY-MM-DD HH:mm"); 960 | var m2 = jalaliMoment("2016-02-04 07:00", "YYYY-MM-DD HH:mm"); 961 | var m3 = jalaliMoment("2016-02-03 06:00", "YYYY-MM-DD HH:mm"); 962 | var m4 = jalaliMoment("2016-02-05 06:00", "YYYY-MM-DD HH:mm"); 963 | m1.isSame(m2, "jday").should.be.equal(true); 964 | m1.isSame(m3, "jday").should.be.equal(false); 965 | m1.isSame(m4, "jday").should.be.equal(false); 966 | m2.isSame(m3, "jday").should.be.equal(false); 967 | m2.isSame(m4, "jday").should.be.equal(false); 968 | m3.isSame(m4, "jday").should.be.equal(false); 969 | }); 970 | }); 971 | describe("#parse persian date", function (){ 972 | it("fill date with another locale", function () { 973 | jalaliMoment.locale("en"); 974 | var m1 = jalaliMoment.from("1367/11/04", "fa", "YYYY/MM/DD"); 975 | m1.format("jYYYY/jMM/jDD").should.be.equal("1367/11/04"); 976 | m1.format("YYYY/MM/DD").should.be.equal("1989/01/24"); 977 | var m2 = jalaliMoment.from("11/1367/04", "fa", "MM/YYYY/DD"); 978 | m1.format("YYYY/MM/DD").should.be.equal("1989/01/24"); 979 | }); 980 | }); 981 | describe("#switch calendar systems", function (){ 982 | it("gregorian is default system", function () { 983 | var m1 = jalaliMoment("1989/01/24","YYYY/MM/DD"); 984 | m1.format("jYYYY/jMM/jDD").should.be.equal("1367/11/04"); 985 | m1.format("YYYY/MM/DD").should.be.equal("1989/01/24"); 986 | m1.isBetween(m1.clone().subtract(1, "day"), m1.clone().add(1, "day"), "day", "[]").should.be.equal(true); 987 | m1.clone().subtract(2, "d").isBetween(m1.clone().subtract(1, "day"), m1.clone().add(1, "day"), "day", "[]").should.be.equal(false); 988 | 989 | jalaliMoment().isBetween(jalaliMoment().subtract(1, "day"), jalaliMoment().add(1, "day"), "day", "[]").should.be.equal(true); 990 | jalaliMoment().subtract(2, "d").isBetween(jalaliMoment().subtract(1, "day"), jalaliMoment().add(1, "day"), "day", "[]").should.be.equal(false); 991 | }); 992 | it("change locale globally should change the whole instances system", function () { 993 | jalaliMoment.locale("fa"); 994 | var m1 = jalaliMoment("1367/11/04","YYYY/MM/DD"); 995 | 996 | m1.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 997 | m1.locale("en"); 998 | m1.format("YYYY/MM/DD").should.be.equal("1989/01/24"); 999 | }); 1000 | it("test changeSystemByItsLocale ", function () { 1001 | var m1 = jalaliMoment("1367/11/04","jYYYY/jMM/jDD"); 1002 | m1.locale("fa"); 1003 | m1.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 1004 | m1.locale("en"); 1005 | m1.format("YYYY/MM/DD").should.be.equal("1989/01/24"); 1006 | }); 1007 | }); 1008 | describe("#clone should not affect on calendar system", function () { 1009 | it("instance locale and clone", function () { 1010 | jalaliMoment.locale("en"); 1011 | var m1 = jalaliMoment("1367/11/04","jYYYY/jMM/jDD"); 1012 | m1.locale("fa"); 1013 | m1.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 1014 | var m2 = m1.clone(); 1015 | m2.subtract(1, "day"); 1016 | m2.format("YYYY/MM/DD").should.be.equal("1367/11/03"); 1017 | m2.subtract(1, "day"); 1018 | m2.clone().format("YYYY/MM/DD").should.be.equal("1367/11/02"); 1019 | }); 1020 | it("global locale and clone", function () { 1021 | jalaliMoment.locale("fa"); 1022 | var m1 = jalaliMoment("1367/11/04","YYYY/MM/DD"); 1023 | m1.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 1024 | var m2 = m1.clone(); 1025 | m2.format("YYYY/MM/DD").should.be.equal("1367/11/04"); 1026 | m2.subtract(1, "day"); 1027 | m2.clone().format("YYYY/MM/DD").should.be.equal("1367/11/03"); 1028 | }); 1029 | }); 1030 | describe("add or subtract when global locale is not as we expected", function () { 1031 | it("instance locale and clone", function () { 1032 | jalaliMoment.locale("en"); 1033 | 1034 | var m1 = jalaliMoment("1395/12/30","jYYYY/jMM/jDD").locale("fa"); 1035 | m1.format("YYYY/MM/DD").should.be.equal("1395/12/30"); 1036 | 1037 | m1.subtract(1, "month"); 1038 | m1.format("YYYY/MM/DD").should.be.equal("1395/11/30"); 1039 | 1040 | m1.subtract(1, "year"); 1041 | m1.format("YYYY/MM/DD").should.be.equal("1394/11/30"); 1042 | }); 1043 | }); 1044 | describe("test utc time", function () { 1045 | it("utc jalaliMoment", function () { 1046 | jalaliMoment.locale("en"); 1047 | var m1 = jalaliMoment("1395/12/30", "jYYYY/jMM/jDD", "fa", true).locale("fa"); 1048 | m1.format("YYYY/MM/DD").should.be.equal("1395/12/30"); 1049 | }); 1050 | }); 1051 | describe("test locale data", function () { 1052 | it("en locale", function () { 1053 | jalaliMoment().localeData().jMonths().should.have.lengthOf(12); 1054 | jalaliMoment().localeData().jMonthsShort().should.have.lengthOf(12); 1055 | }); 1056 | it("fa locale", function () { 1057 | jalaliMoment().locale("fa").localeData().jMonths().should.have.lengthOf(12); 1058 | jalaliMoment().locale("fa").localeData().jMonthsShort().should.have.lengthOf(12); 1059 | }); 1060 | }); 1061 | describe("getting year and month in both locale", function () { 1062 | it("en locale", function () { 1063 | jalaliMoment.locale("en"); 1064 | var now = jalaliMoment(); 1065 | now.locale("en"); 1066 | var month = +now.format("M"); 1067 | var year = +now.format("YYYY"); 1068 | now.year().should.be.equal(year); 1069 | now.month().should.be.equal(month - 1); 1070 | }); 1071 | it("fa locale", function () { 1072 | jalaliMoment.locale("en"); 1073 | var now = jalaliMoment(); 1074 | now.locale("fa"); 1075 | var month = +now.format("M"); 1076 | var year = +now.format("YYYY"); 1077 | now.year().should.be.equal(year); 1078 | now.month().should.be.equal(month - 1); 1079 | }); 1080 | }); 1081 | describe("getting day of year in both locale", function () { 1082 | jalaliMoment.locale("en"); 1083 | var now = jalaliMoment(); 1084 | it("day of year with en locale", function () { 1085 | now.locale("en"); 1086 | var dayOfYear = +now.format("DDDD"); 1087 | now.dayOfYear().should.be.equal(dayOfYear); 1088 | }); 1089 | it("day of year with fa locale", function () { 1090 | now.locale("fa"); 1091 | var dayOfYear = +now.format("DDDD"); 1092 | now.dayOfYear().should.be.equal(dayOfYear); 1093 | }); 1094 | }); 1095 | describe("getting week fa locale", function () { 1096 | jalaliMoment.locale("en"); 1097 | var now = jalaliMoment(); 1098 | now.locale("fa"); 1099 | it("week with fa locale", function () { 1100 | now.week().should.be.equal(now.jWeek()); 1101 | }); 1102 | it("week year with fa locale", function () { 1103 | now.weekYear().should.be.equal(now.jWeekYear()); 1104 | }); 1105 | }); 1106 | describe("getting week fa locale", function () { 1107 | jalaliMoment.locale("en"); 1108 | var now = jalaliMoment(); 1109 | now.locale("fa"); 1110 | it("week with fa locale", function () { 1111 | now.week().should.be.equal(now.jWeek()); 1112 | }); 1113 | it("week year with fa locale", function () { 1114 | now.weekYear().should.be.equal(now.jWeekYear()); 1115 | }); 1116 | }); 1117 | describe("getting from now with fa locale", function () { 1118 | it("just now", function () { 1119 | jalaliMoment.locale("fa"); 1120 | var now = jalaliMoment(); 1121 | now.locale("fa"); 1122 | now.fromNow().should.be.equal("چند ثانیه پیش"); 1123 | }); 1124 | it("10 seconds ago", function () { 1125 | jalaliMoment.locale("fa"); 1126 | var now = jalaliMoment(); 1127 | now.locale("fa"); 1128 | now.subtract(10, "s"); 1129 | now.fromNow().should.be.equal("چند ثانیه پیش"); 1130 | }); 1131 | it("100 seconds ago", function () { 1132 | jalaliMoment.locale("fa"); 1133 | var now = jalaliMoment(); 1134 | now.locale("fa"); 1135 | now.subtract(100, "s"); 1136 | now.fromNow().should.be.equal("2 دقیقه پیش"); 1137 | }); 1138 | it("5 days ago", function () { 1139 | jalaliMoment.locale("fa"); 1140 | var now = jalaliMoment(); 1141 | now.locale("fa"); 1142 | now.subtract(5, "d"); 1143 | now.fromNow().should.be.equal("5 روز پیش"); 1144 | }); 1145 | it("1 month ago", function () { 1146 | jalaliMoment.locale("fa"); 1147 | var now = jalaliMoment(); 1148 | now.locale("fa"); 1149 | now.subtract(1, "months"); 1150 | now.fromNow().should.be.equal("1 ماه پیش"); 1151 | }); 1152 | it("3 years ago", function () { 1153 | jalaliMoment.locale("fa"); 1154 | var now = jalaliMoment(); 1155 | now.locale("fa"); 1156 | now.subtract(3, "year"); 1157 | now.fromNow().should.be.equal("3 سال پیش"); 1158 | }); 1159 | }); 1160 | describe("use gregorian calendar parser in 'fa' locale", function () { 1161 | it("use jalali calendar when useGregorianParser is false in fa locale", function () { 1162 | jalaliMoment.locale("fa", { useGregorianParser: false }); 1163 | jalaliMoment("1370-10-17").format("YYYY-MM-DD").should.be.equal("1370-10-17"); 1164 | }); 1165 | it("parse using gregorian calendar in fa locale", function () { 1166 | jalaliMoment.locale("fa", { useGregorianParser: true }); 1167 | jalaliMoment("2019-01-17T08:19:19.975Z").format("YYYY-MM-DD").should.be.equal("1397-10-27"); 1168 | jalaliMoment("2019-02-23").format("YYYY-MM-DD").should.be.equal("1397-12-04"); 1169 | }); 1170 | }); 1171 | 1172 | describe("jalaliMoment toISOString", function () { 1173 | jalaliMoment.locale("en"); 1174 | it("toISOString(false) with 00:00 time and GMT+ timezone should decrease day", function () { 1175 | // const date = jalaliMoment("2020-11-23 +03:30", 'YYYY-MM-DD ZZ').utcOffset("+03:30"); 1176 | const date = jalaliMoment.utc("2020-11-23 +03:30", 'YYYY-MM-DD ZZ').utcOffset("+03:30"); 1177 | const isoString = date.toISOString(false); 1178 | const dateWithoutTimezone = jalaliMoment(isoString.split('T')[0]); 1179 | date.date().should.be.equal(dateWithoutTimezone.date() + 1); 1180 | date.format("YYYY-MM-DD").should.not.equal(dateWithoutTimezone.format("YYYY-MM-DD")); 1181 | }); 1182 | 1183 | it("toISOString(true) with 00:00 time and GMT+ timezone should preserve date", function () { 1184 | const date = jalaliMoment("2020-11-23").utcOffset("+03:30"); 1185 | const isoString = date.toISOString(true); 1186 | const dateWithoutTimezone = jalaliMoment(isoString.split('T')[0]); 1187 | date.format("YYYY-MM-DD").should.be.equal(dateWithoutTimezone.format("YYYY-MM-DD")); 1188 | }); 1189 | }); 1190 | 1191 | describe("compare jalaliMoment and moment", function () { 1192 | it("utc should be the same", function () { 1193 | const a = jalaliMoment.utc("09:30", "HH:mm"); 1194 | const b = moment.utc("09:30", "HH:mm"); 1195 | a.locale('en').format('YYMMDD-HH:mm').should.be.equal(b.format('YYMMDD-HH:mm')); 1196 | }); 1197 | }); 1198 | describe("jmoment vs moment", function () { 1199 | it("ISO_8601", function () { 1200 | //https://github.com/fingerpich/jalali-moment/issues/70 1201 | const d1 = moment('2019-10-26', moment.ISO_8601).format(); 1202 | const d2 = jalaliMoment('2019-10-26', moment.ISO_8601).format(); 1203 | d1.should.be.equal(d2); 1204 | }); 1205 | it("diff locale fa", function () { 1206 | //https://github.com/fingerpich/jalali-moment/issues/78 1207 | const testDates = [ 1208 | { 1209 | d1: jalaliMoment("2020-03-20").locale("fa"), //1399/1/1 1210 | d2: jalaliMoment("2021-03-21").locale("fa"), //1400/1/1 1211 | diff: "year", 1212 | result: -1, 1213 | }, 1214 | { 1215 | d1: jalaliMoment("2021-03-21").locale("fa"), 1216 | d2: jalaliMoment("2020-03-20").locale("fa"), 1217 | diff: "year", 1218 | result: 1, 1219 | }, 1220 | { 1221 | d1: jalaliMoment("2020-03-21").locale("fa"), //1399/1/2 1222 | d2: jalaliMoment("2021-03-21").locale("fa"), //1400/1/1 1223 | diff: "year", 1224 | result: 0, 1225 | }, 1226 | { 1227 | d1: jalaliMoment("2020-03-20").locale("fa"), 1228 | d2: jalaliMoment("2021-03-21").locale("fa"), 1229 | diff: "month", 1230 | result: -12, 1231 | }, 1232 | { 1233 | d1: jalaliMoment("2021-03-21").locale("fa"), 1234 | d2: jalaliMoment("2020-03-20").locale("fa"), 1235 | diff: "month", 1236 | result: 12, 1237 | }, 1238 | { 1239 | d1: jalaliMoment("2020-07-21").locale("fa"), //1399/04/31 1240 | d2: jalaliMoment("2020-06-21").locale("fa"), //1399/04/01 1241 | diff: "month", 1242 | result: 0, 1243 | }, 1244 | { 1245 | d1: jalaliMoment("2020-07-21").locale("fa"), //1399/04/31 1246 | d2: jalaliMoment("2020-06-20").locale("fa"), //1399/03/31 1247 | diff: "month", 1248 | result: 1, 1249 | }, 1250 | { 1251 | d1: jalaliMoment("2021-03-21").locale("fa"), 1252 | d2: jalaliMoment("2020-03-20").locale("fa"), 1253 | diff: "day", 1254 | result: 366, //1399 is leap year 1255 | }, 1256 | { 1257 | d1: jalaliMoment("2020-07-21").locale("fa"), //1399/04/31 1258 | d2: jalaliMoment("2020-06-20").locale("fa"), //1399/03/31 1259 | diff: "day", 1260 | result: 31, 1261 | }, 1262 | ] 1263 | 1264 | testDates.forEach((date) => { 1265 | date.d1.diff(date.d2, date.diff).should.be.equal(date.result) 1266 | }) 1267 | }); 1268 | }); 1269 | }); 1270 | `` --------------------------------------------------------------------------------