├── .editorconfig
├── .github
└── ISSUE_TEMPLATE.md
├── .gitignore
├── .husky
└── pre-commit
├── .travis.yml
├── .vscode
└── settings.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── angular.json
├── jest.config.js
├── ng-package.json
├── ng-package.prod.json
├── package-lock.json
├── package.json
├── prettier.config.js
├── setupJest.ts
├── src
├── add.pipe.spec.ts
├── add.pipe.ts
├── calendar.pipe.spec.ts
├── calendar.pipe.ts
├── date-format.pipe.spec.ts
├── date-format.pipe.ts
├── difference.pipe.spec.ts
├── difference.pipe.ts
├── duration.pipe.spec.ts
├── duration.pipe.ts
├── from-unix.pipe.spec.ts
├── from-unix.pipe.ts
├── from-utc.pipe.spec.ts
├── from-utc.pipe.ts
├── index.ts
├── is-after.pipe.spec.ts
├── is-after.pipe.ts
├── is-before.pipe.spec.ts
├── is-before.pipe.ts
├── local.pipe.spec.ts
├── local.pipe.ts
├── locale.pipe.spec.ts
├── locale.pipe.ts
├── moment-options.ts
├── moment.module.ts
├── parse-zone.pipe.spec.ts
├── parse-zone.pipe.ts
├── parse.pipe.spec.ts
├── parse.pipe.ts
├── subtract.pipe.spec.ts
├── subtract.pipe.ts
├── time-ago.pipe.spec.ts
├── time-ago.pipe.ts
├── utc.pipe.spec.ts
└── utc.pipe.ts
├── tsconfig.json
├── tsconfig.lint.json
├── tsconfig.spec.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 | end_of_line = lf
13 | charset = utf-8
14 | trim_trailing_whitespace = true
15 | insert_final_newline = true
16 |
17 | [*.md]
18 | trim_trailing_whitespace = false
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | **Description of the Issue and Steps to Reproduce:**
2 |
3 | Did you search for duplicate issue? [Yes / No]
4 |
5 | Please describe the issue and steps to reproduce, preferably with a code sample / plunker:
6 |
7 |
8 |
9 |
10 |
11 |
12 | *Ensure your issue is isolated to ngx-moment. Issues involving third party tools will be closed unless submitted by the tool's author/maintainer.*
13 |
14 | **Environment:**
15 |
16 | Please answer the following questions:
17 |
18 | * Angular version?
19 | * TypeScript version?
20 | * `moment` version?
21 | * Are you using `moment-timezone`?
22 | * Are you using the angular-cli?
23 | * Using Rollup/Webpack/System.js/Ionic/similar?
24 |
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .history
2 | .idea
3 | node_modules
4 | .angular
5 | *.log
6 | dist
7 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npm test
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | sudo: false
3 | node_js:
4 | - "10"
5 | - "12"
6 | - "14"
7 | env:
8 | - TZ=utc
9 | - TZ=Etc/GMT-14
10 | - TZ=Etc/GMT+12
11 | - TZ=Asia/Katmandu
12 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "**/*.js": {
5 | "when": "$(basename).ts"
6 | },
7 | "**/*.js.map": true,
8 | "**/*.d.ts": {
9 | "when": "$(basename).ts"
10 | }
11 | }
12 | ,
13 | "typescript.tsdk": "./node_modules/typescript/lib"
14 | }
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 6.0.2 - 2021-12-22
4 | - Fix moment import via jsnext entry point (use default import interop) (see [#245](https://github.com/urish/ngx-moment/issues/245))
5 |
6 | ## 6.0.1 - 2021-12-20
7 | - Fix build issue (see [#273](https://github.com/urish/ngx-moment/issues/273))_
8 |
9 | ## 6.0.0 - 2021-11-30
10 | - Support for Angular 13 + Ivy
11 |
12 | ## 5.0.0 - 2020-07-03
13 | - fix: support for Angular 10 (see [#240](https://github.com/urish/ngx-moment/issues/240))
14 | - breaking: drop support for Angular < 7
15 |
16 | ## 4.0.1 - 2020-06-12
17 | - republish to npm without ngcc backup files
18 |
19 | ## 4.0.0 - 2020-06-12
20 | - fix: correct input types for pipes 906e40c
21 | - chore(deps): angular 9, typescript 3.8 9966a9a
22 | - chore: reformat all code with prettier 10fe5c51
23 | - docs: remove system.js instructions from README
24 |
25 | ## 3.5.0 - 2019-11-08
26 | - feat: add `formatFn` argument to `amTimeAgo` ([#213](https://github.com/urish/ngx-moment/pull/213), contributed by [chaoyangnz](https://github.com/chaoyangnz))
27 | - feat: add `format|formats` to from-utc pipe and parse-pipe ([#215](https://github.com/urish/ngx-moment/pull/215), contributed by [gigadie](https://github.com/gigadie))
28 | - fix: improve `amLocale` compability with Angular Ivy ([#226](https://github.com/urish/ngx-moment/pull/226), contributed by [sobanieca](https://github.com/sobanieca))
29 |
30 | ## 3.4.0 - 2019-03-07
31 | - feat: add amIsBefore, amIsAfter pipes ([#208](https://github.com/urish/ngx-moment/pull/208), contributed by [StickNitro](https://github.com/StickNitro))
32 | - Ability to provide options to the MomentModule ([#209](https://github.com/urish/ngx-moment/pull/209), contributed by [StickNitro](https://github.com/StickNitro))
33 | - fix: Improved Text Update on locale change when not using MomentInput ([#210](https://github.com/urish/ngx-moment/pull/210), contributed by [jensweigele](https://github.com/jensweigele))
34 |
35 | ## 3.3.0 - 2018-12-09
36 | - fix: Allow using all supported Moment inputs with TimeAgoPipe ([#206](https://github.com/urish/ngx-moment/pull/206), contributed by [theodorejb](https://github.com/theodorejb))
37 |
38 | ## 3.2.0 - 2018-10-30
39 | - Angular 7 support ([#203](https://github.com/urish/ngx-moment/issues/203))
40 |
41 | ## 3.1.0 - 2018-07-01
42 | - Add 'amParseZone' pipe ([#198](https://github.com/urish/ngx-moment/pull/198), contributed by [davidballester](https://github.com/davidballester))
43 |
44 | ## 3.0.1 - 2018-06-07
45 | - Update installation instruction in readme (see [#194](https://github.com/urish/ngx-moment/issues/194))
46 |
47 | ## 3.0.0 - 2018-06-02
48 | - Make `moment` a peerDependency instead of dependency (see [#149](https://github.com/urish/ngx-moment/issues/149) for discussion)
49 |
50 | When upgrading to this version, make sure to `npm install --save moment`.
51 |
52 | ## 2.0.0 - 2018-04-25
53 | - Rename package to ngx-moment
54 | - Migrate project to the Angular CLI
55 | - Switch to [Angular Package Format](https://docs.google.com/document/d/1CZC2rcpxffTDfRDs6p1cfbmKNLA6x5O-NtkJglDaBVs/edit), (using [ngPackagr](http://spektrakel.de/ng-packagr/))
56 |
57 | 2.0.0-beta.0 and 2.0.0-rc.0 are aliases for this version.
58 |
59 | ## 1.9.0 - 2018-05-03
60 | - Fix: update momentjs version ([#190](https://github.com/urish/ngx-moment/issues/190))
61 | - Fix: amTimeAgo pipe updates it's output when locale changes ([#188](https://github.com/urish/ngx-moment/pull/188), contributed by [lukasz-kusnierz](https://github.com/lukasz-kusnierz))
62 |
63 | ## 1.8.0 - 2018-01-23
64 | - Fix: Remove `node_modules` from compiled version ([#187](https://github.com/urish/ngx-moment/pull/187), contributed by [wachri](https://github.com/wachri))
65 |
66 | ## 1.7.1 - 2017-12-22
67 | - Fix bug where FromUtcPipe was being imported instead of exported ([#180](https://github.com/urish/ngx-moment/pull/180), contributed by [fshin123](https://github.com/fshin123))
68 | - test: fix amLocal tests to pass regardless of timezone
69 |
70 | ## 1.7.0 - 2017-08-19
71 | - Add `amFromUtc` pipe ([#163](https://github.com/urish/ngx-moment/pull/163), contributed by [connormlewis](https://github.com/connormlewis))
72 |
73 | ## 1.6.0 - 2017-07-18
74 | - Add `amLocal` pipe ([#153](https://github.com/urish/ngx-moment/pull/153), contributed by [benwilkins](https://github.com/benwilkins))
75 |
76 | ## 1.5.0 - 2017-07-14
77 | - Add `amLocale` pipe ([#155](https://github.com/urish/ngx-moment/pull/155), contributed by [FallenRiteMonk](https://github.com/FallenRiteMonk))
78 | - Migrate testing framework to jest
79 |
80 | ## 1.4.0 - 2017-06-18
81 | - Add `amParse` pipe to enable parsing of custom-formatted date string ([#148](https://github.com/urish/ngx-moment/pull/148), contributed by [vin-car](https://github.com/vin-car))
82 |
83 | ## 1.3.3 - 2017-03-18
84 | - Fix: `amCalendar` causes protractor to timeout on waiting async Angular ([#135](https://github.com/urish/ngx-moment/pull/135), contributed by [romanovma](https://github.com/romanovma))
85 |
86 | ## 1.3.2 - 2017-03-17
87 | - Fix: Add missing `amAdd` and `amSubtract` pipes to the NgModule ([#134](https://github.com/urish/ngx-moment/pull/134), contributed by [datencia](https://github.com/datencia))
88 |
89 | ## 1.3.1 - 2017-03-16
90 | - Add missing `amAdd` and `amSubtract` pipes (fixes [#130](https://github.com/urish/ngx-moment/issues/130))
91 |
92 | ## 1.3.0 - 2017-03-10
93 | - Enable Angular 4 as peer dependency
94 |
95 | ## 1.2.0 - 2017-02-09
96 | - Add `amUtc` pipe ([#121](https://github.com/urish/ngx-moment/pull/121), contributed by [bodnarbm](https://github.com/bodnarbm))
97 |
98 | ## 1.1.0 - 2017-01-09
99 | Happy new year!
100 |
101 | - Add `referenceTime` and `format` args to `amCalendar` ([#64](https://github.com/urish/ngx-moment/pull/64), contributed by [irsick](https://github.com/irsick))
102 | - Add `amAdd` and `amSubtract` pipes ([#113](https://github.com/urish/ngx-moment/pull/113), contributed by [dustin486](https://github.com/dustin486))
103 | - Fix: Do not import whole Rx.js library ([#117](https://github.com/urish/ngx-moment/pull/117), contributed by [FabienDehopre](https://github.com/FabienDehopre))
104 |
105 | ## 1.0.0 - 2016-12-01
106 | Promoted 1.0.0-rc.1 to final release
107 |
108 | ## 1.0.0-rc.1 - 2016-11-11
109 | *** Breaking change: Requires moment 2.16.0 or newer
110 |
111 | - Fix “Expression has changed after it was checked” ([#111](https://github.com/urish/ngx-moment/pull/111), contributed by [nithril](https://github.com/nithril))
112 | - Fix "Module 'moment' has no exported member 'UnitOfTime'" ([#112](https://github.com/urish/ngx-moment/issues/112))
113 |
114 | ## 1.0.0-beta.6 - 2016-10-24
115 | *** Breaking change: typescript sources are no longer published in the npm package
116 |
117 | - Inline sources in the source map file, should fix [#96](https://github.com/urish/ngx-moment/issues/96).
118 | - Handle undefined dates in `amDateFormat` pipe ([#105](https://github.com/urish/ngx-moment/pull/105/files), contributed by [amcdnl](https://github.com/amcdnl))
119 |
120 | ## 1.0.0-beta.5 - 2016-10-13
121 |
122 | *** Breaking change: source files renamed, which could affect your imports:
123 |
124 | import { TimeAgoPipe } from 'angular-moment/TimeAgoPipe';
125 |
126 | now becomes:
127 |
128 | import { TimeAgoPipe } from 'angular-moment/time-ago.pipe';
129 |
130 | All changes:
131 |
132 | - Rename source files to follow [Angular 2 Style Guide conventions](https://angular.io/styleguide#!#02-02)
133 | - Require `moment` >= 2.13.0, and remove `@types/moment` from our dependencies (as it is already included in `moment`)
134 |
135 | ## 1.0.0-beta.4 - 2016-10-06
136 | - Add support for server side pre-rendering ([#89](https://github.com/urish/ngx-moment/pull/89), contributed by [https://github.com/jmezach](https://github.com/jmezach))
137 | - Fix a bug caused TimeAgo and Calendar pipes not to update automatically ([#94](https://github.com/urish/ngx-moment/pull/94))
138 | - Add `@types/moment` to package dependencies (see [#91](https://github.com/urish/ngx-moment/issues/91))
139 |
140 | ## 1.0.0-beta.3 - 2016-10-04
141 | - Fix exports for Rollup / Ionic 2 users ([#86](https://github.com/urish/ngx-moment/pull/86), contributed by [TheMadBug](https://github.com/TheMadBug))
142 | - Protractor fix: run long standing timeouts outside of angular zones ([#74](https://github.com/urish/ngx-moment/pull/74), contributed by [tiagoroldao](https://github.com/tiagoroldao))
143 |
144 | ## 1.0.0-beta.2 - 2016-10-01
145 | - Switch to Typescript 2.0
146 | - Angular 2 AoT (Ahead of Time) template compilation support ([#68](https://github.com/urish/ngx-moment/issues/68))
147 | - Removed impure flags from pure Pipes: `amDateFormat` and `amDifference` ([#75](https://github.com/urish/ngx-moment/pull/75), contributed by [tiagoroldao](https://github.com/tiagoroldao))
148 |
149 | ## 1.0.0-beta.1 - 2016-08-16
150 | - Support angular-2.0.0-rc.5 NgModules, see [README](README.md) for details.
151 |
152 | ## 0.8.2 - 2016-08-01
153 | - Add `amDifference` pipe ([#54](https://github.com/urish/ngx-moment/pull/54), contributed by [josx](https://github.com/josx))
154 |
155 | ## 0.8.1 - 2016-07-03
156 | - Add `omitSuffix` parameter to `amTimeAgo` pipe ([#47](https://github.com/urish/ngx-moment/pull/47), contributed by [bzums](https://github.com/bzums))
157 |
158 | ## 0.8.0 - 2016-05-22
159 | - Publish typescript sources under `src` folder, should fix Ionic 2 issues such as [#28](https://github.com/urish/ngx-moment/issues/28) and [#33](https://github.com/urish/ngx-moment/issues/33).
160 |
161 | ## 0.7.0 - 2016-05-03
162 | - Align with the angular 2.0.0-rc.0 and the new angular packaging system
163 |
164 | ## 0.6.0 - 2016-04-28
165 | - Align with angular 2.0.0-beta.16 ([#32](https://github.com/urish/ngx-moment/pull/32), contributed by [fknop](https://github.com/fknop))
166 |
167 | ## 0.5.0 - 2016-04-08
168 | - Move `angular2` from npm `dependencies` to `peerDependencies` (see [#24](https://github.com/urish/ngx-moment/pull/24))
169 | - Add `amDuration` pipe ([#29](https://github.com/urish/ngx-moment/pull/29), contributed by [xenolinguist](https://github.com/xenolinguist))
170 |
171 | ## 0.4.3 - 2016-03-06
172 | - include `amFromUnix` pipe in the package's exports
173 | - publish our `typings.json` to npm
174 |
175 | ## 0.4.2 - 2016-02-24
176 | - add `amFromUnix` pipe ([#16](https://github.com/urish/ngx-moment/pull/16), contributed by [lanocturne](https://github.com/lanocturne))
177 |
178 | ## 0.4.1 - 2016-02-21
179 | - Don't run `typings install` on postinstall (fixes [#13](https://github.com/urish/ngx-moment/issues/13))
180 |
181 | ## 0.4.0 - 2016-02-16
182 | - Switch from `tsd` to `typings`, stop publishing the `moment.js` typings to npm.
183 | - Additional unit-tests
184 |
185 | Note: You may need to manually install moment.js typings, by running `typings install --save moment` in your project directory.
186 |
187 | ## 0.3.0 - 2016-01-27
188 | - add `amDateFormat` pipe ([#9](https://github.com/urish/ngx-moment/pull/9), contributed by [andreialecu](https://github.com/andreialecu))
189 | - refactor: remove the `supports()` from all the pipes (it is no longer used as of angular2-beta)
190 |
191 | ## 0.2.1 - 2016-01-16
192 | - bugfix: wrong method name for cleanup, caused resource leak ([#8](https://github.com/urish/ngx-moment/pull/8), contributed by [andreialecu](https://github.com/andreialecu))
193 |
194 | ## 0.2.0 - 2016-01-12
195 | - add `amCalendar` pipe ([#6](https://github.com/urish/ngx-moment/pull/6), contributed by [andreialecu](https://github.com/andreialecu))
196 |
197 | ## 0.1.1 - 2015-12-18
198 | - Fix 'Cannot use in app due to triple-slash references' typescript error ([#2](https://github.com/urish/ngx-moment/issues/2))
199 |
200 | ## 0.1.0 - 2015-12-15
201 | - Align with angular 2.0.0-beta.0
202 |
203 | ## 0.0.5 - 2015-11-12
204 | - Align with angular-2.0.0-alpha.46
205 |
206 | ## 0.0.4 - 2015-10-25
207 | - Add ES5 transpiled version and typescript definitions (.d.ts) file to the published npm package
208 |
209 | ## 0.0.3 - 2015-10-22
210 | - Align with angular-2.0.0-alpha.44
211 |
212 | ## 0.0.2 - 2015-09-18
213 | - Align with angular-2.0.0-alpha.37
214 |
215 | ## 0.0.1 - 2015-08-25
216 |
217 | - Initial release
218 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guide
2 |
3 | Contributing to `ngx-moment` is fairly easy. This document shows you how to
4 | get the project, run all provided tests and generate a production ready build.
5 |
6 | It also covers provided npm scripts, that help you developing on `ngx-moment`.
7 |
8 | ## Dependencies
9 |
10 | To make sure, that the following instructions work, please install the following dependencies
11 | on you machine:
12 |
13 | - Node.js
14 | - npm
15 | - Git
16 |
17 | ## Installation
18 |
19 | To get the source of `ngx-moment` clone the git repository via:
20 |
21 | `git clone https://github.com/urish/ngx-moment`
22 |
23 | This will clone the complete source to your local machine. Navigate to the project folder
24 | and install all needed dependencies via **npm**:
25 |
26 | `npm install`
27 |
28 | Well done! ngx-moment is now installed and ready to be built.
29 |
30 | ## Building
31 |
32 | `ngx-moment` comes with a few **npm scripts** which help you to automate
33 | the development process. The following npm scripts are provided:
34 |
35 | #### npm test
36 |
37 | `npm test` compiles the typescript code into javascript, and then runs the unit
38 | tests, which are located in `src/*.spec.ts`. The task uses the [jest test runner](https://facebook.github.io/jest/).
39 |
40 | #### npm run prepublish
41 |
42 | `npm run prepublish` compiles the typescript code into javascript.
43 |
44 | ## Contributing/Submitting changes
45 |
46 | - Checkout a new branch based on `master` and name it to what you intend to do:
47 | - Example:
48 | ````
49 | $ git checkout -b BRANCH_NAME
50 | ````
51 | - Use one branch per fix/feature
52 | - Make your changes
53 | - Make sure to provide a spec for unit tests (see [time-ago.pipe.spec.ts](src/time-ago.pipe.spec.ts) for example)
54 | - Run your tests with `npm test`
55 | - When all tests pass, everything's fine
56 | - Commit your changes
57 | - Please provide a git message which explains what you've done
58 | - Commit to the forked repository
59 | - Make a pull request
60 |
61 | If you follow these instructions, your PR will land pretty safely in the main repo!
62 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013-2020 Uri Shaked and contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ngx-moment
2 |
3 | moment.js pipes for Angular
4 |
5 | [](https://travis-ci.org/urish/ngx-moment)
6 | [](https://www.npmjs.com/package/ngx-moment)
7 |
8 | This module works with Angular 7.0.0 and newer.
9 |
10 | For older Angular versions, please install [angular2-moment](https://npmjs.org/package/angular2-moment). For the AngularJS, please check out [angular-moment](https://github.com/urish/angular-moment).
11 |
12 | Installation
13 | ------------
14 |
15 | ```bash
16 | npm install --save moment ngx-moment
17 | ```
18 |
19 | or if you use yarn:
20 |
21 | ```bash
22 | yarn add moment ngx-moment
23 | ```
24 |
25 | Usage
26 | -----
27 |
28 | Import `MomentModule` into your app's modules:
29 |
30 | ``` typescript
31 | import { MomentModule } from 'ngx-moment';
32 |
33 | @NgModule({
34 | imports: [
35 | MomentModule
36 | ]
37 | })
38 | ```
39 |
40 | If you would like to supply any `NgxMomentOptions` that will be made available to the pipes you can also use:
41 |
42 | ```typescript
43 | import { MomentModule } from 'ngx-moment';
44 |
45 | @NgModule({
46 | imports: [
47 | MomentModule.forRoot({
48 | relativeTimeThresholdOptions: {
49 | 'm': 59
50 | }
51 | })
52 | ]
53 | })
54 | ```
55 |
56 | This makes all the `ngx-moment` pipes available for use in your app components.
57 |
58 | Available pipes
59 | ---------------
60 |
61 | ## amTimeAgo pipe
62 | Takes an optional `omitSuffix` argument that defaults to `false` and another optional `formatFn` function which can be used to customise the format of the time ago text.
63 |
64 | ``` typescript
65 | @Component({
66 | selector: 'app',
67 | template: `
68 | Last updated: {{myDate | amTimeAgo}}
69 | `
70 | })
71 | ```
72 |
73 | Prints `Last updated: a few seconds ago`
74 |
75 | ``` typescript
76 | @Component({
77 | selector: 'app',
78 | template: `
79 | Last updated: {{myDate | amTimeAgo:true}}
80 | `
81 | })
82 | ```
83 |
84 | Prints `Last updated: a few seconds`
85 |
86 | ## amCalendar pipe
87 | Takes optional `referenceTime` argument (defaults to now)
88 | and `formats` argument that could be output formats object or callback function.
89 | See [momentjs docs](http://momentjs.com/docs/#/displaying/calendar-time/) for details.
90 |
91 | ``` typescript
92 | @Component({
93 | selector: 'app',
94 | template: `
95 | Last updated: {{myDate | amCalendar}}
96 | `
97 | })
98 | ```
99 |
100 | Prints `Last updated: Today at 14:00` (default referenceTime is today by default)
101 |
102 | ``` typescript
103 | @Component({
104 | selector: 'app',
105 | template: `
106 | Last updated:
107 | `
108 | })
109 | export class AppComponent {
110 | nextDay: Date;
111 |
112 | constructor() {
113 | this.nextDay = new Date();
114 | nextDay.setDate(nextDay.getDate() + 1);
115 | }
116 | }
117 | ```
118 |
119 | Prints `Last updated: Yesterday at 14:00` (referenceTime is tomorrow)
120 |
121 | ``` typescript
122 | @Component({
123 | selector: 'app',
124 | template: `
125 | Last updated:
126 | `
127 | })
128 | ```
129 |
130 | Prints `Last updated: Same Day at 2:00 PM`
131 |
132 | ## amDateFormat pipe
133 |
134 | ``` typescript
135 | @Component({
136 | selector: 'app',
137 | template: `
138 | Last updated: {{myDate | amDateFormat:'LL'}}
139 | `
140 | })
141 | ```
142 |
143 | Prints `Last updated: January 24, 2016`
144 |
145 | ## amParse pipe
146 |
147 | Parses a custom-formatted date into a moment object that can be used with the other pipes.
148 |
149 | ``` typescript
150 | @Component({
151 | selector: 'app',
152 | template: `
153 | Last updated: {{'24/01/2014' | amParse:'DD/MM/YYYY' | amDateFormat:'LL'}}
154 | `
155 | })
156 | ```
157 |
158 | Prints `Last updated: January 24, 2016`
159 |
160 | The pipe can also accept an array of formats as parameter.
161 |
162 | ``` typescript
163 | @Component({
164 | selector: 'app',
165 | template: `
166 | Last updated: {{'24/01/2014 22:00' | amParse: formats | amDateFormat:'LL'}}
167 | `
168 | })
169 | export class App {
170 |
171 | formats: string[] = ['DD/MM/YYYY HH:mm:ss', 'DD/MM/YYYY HH:mm'];
172 |
173 | constructor() { }
174 |
175 | }
176 | ```
177 |
178 | Prints `Last updated: January 24, 2016`
179 |
180 | ## amLocal pipe
181 |
182 | Converts UTC time to local time.
183 |
184 | ``` typescript
185 | @Component({
186 | selector: 'app',
187 | template: `
188 | Last updated: {{mydate | amLocal | amDateFormat: 'YYYY-MM-DD HH:mm'}}
189 | `
190 | })
191 | ```
192 |
193 | Prints `Last updated 2016-01-24 12:34`
194 |
195 | ## amLocale pipe
196 |
197 | To be used with amDateFormat pipe in order to change locale.
198 |
199 | ``` typescript
200 | @Component({
201 | selector: 'app',
202 | template: `
203 | Last updated: {{'2016-01-24 14:23:45' | amLocale:'en' | amDateFormat:'MMMM Do YYYY, h:mm:ss a'}}
204 | `
205 | })
206 | ```
207 |
208 | Prints `Last updated: January 24th 2016, 2:23:45 pm`
209 |
210 | Note: The locale might have to be imported (e.g. in the app module).
211 |
212 | ``` typescript
213 | import 'moment/locale/de';
214 | ```
215 |
216 | ## amFromUnix pipe
217 |
218 | ``` typescript
219 | @Component({
220 | selector: 'app',
221 | template: `
222 | Last updated: {{ (1456263980 | amFromUnix) | amDateFormat:'hh:mmA'}}
223 | `
224 | })
225 | ```
226 |
227 | Prints `Last updated: 01:46PM`
228 |
229 | ## amDuration pipe
230 |
231 | ``` typescript
232 | @Component({
233 | selector: 'app',
234 | template: `
235 | Uptime: {{ 365 | amDuration:'seconds' }}
236 | `
237 | })
238 | ```
239 |
240 | Prints `Uptime: 6 minutes`
241 |
242 | ## amDifference pipe
243 |
244 | ``` typescript
245 | @Component({
246 | selector: 'app',
247 | template: `
248 | Expiration: {{nextDay | amDifference: today :'days' : true}} days
249 | `
250 | })
251 | ```
252 | Prints `Expiration: 1 days`
253 |
254 | ## amAdd and amSubtract pipes
255 |
256 | Use these pipes to perform date arithmetics. See [momentjs docs](http://momentjs.com/docs/#/manipulating/add/) for details.
257 |
258 | ``` typescript
259 | @Component({
260 | selector: 'app',
261 | template: `
262 | Expiration: {{'2017-03-17T16:55:00.000+01:00' | amAdd: 2 : 'hours' | amDateFormat: 'YYYY-MM-DD HH:mm'}}
263 | `
264 | })
265 | ```
266 | Prints `Expiration: 2017-03-17 18:55`
267 |
268 | ``` typescript
269 | @Component({
270 | selector: 'app',
271 | template: `
272 | Last updated: {{'2017-03-17T16:55:00.000+01:00' | amSubtract: 5 : 'years' | amDateFormat: 'YYYY-MM-DD HH:mm'}}
273 | `
274 | })
275 | ```
276 | Prints `Last updated: 2012-03-17 16:55`
277 |
278 | ## amFromUtc pipe
279 |
280 | Parses the date as UTC and enables mode for subsequent moment operations (such as displaying the time in UTC). This can be combined with `amLocal` to display a UTC date in local time.
281 |
282 | ``` typescript
283 | @Component({
284 | selector: 'app',
285 | template: `
286 | Last updated: {{ '2016-12-31T23:00:00.000-01:00' | amFromUtc | amDateFormat: 'YYYY-MM-DD' }}
287 | `
288 | })
289 | ```
290 |
291 | Prints `Last updated: 2017-01-01`
292 |
293 | It's also possible to specify a different format than the standard ISO8601.
294 |
295 | ``` typescript
296 | @Component({
297 | selector: 'app',
298 | template: `
299 | Last updated: {{ '31/12/2016 23:00-01:00' | amFromUtc: 'DD/MM/YYYY HH:mmZZ' | amDateFormat: 'YYYY-MM-DD' }}
300 | `
301 | })
302 | ```
303 |
304 | Or even an array of formats:
305 |
306 | ``` typescript
307 | @Component({
308 | selector: 'app',
309 | template: `
310 | Last updated: {{ '31/12/2016 23:00-01:00' | amFromUtc: formats | amDateFormat: 'YYYY-MM-DD' }}
311 | `
312 | })
313 | export class App {
314 |
315 | formats: string[] = ['DD/MM/YYYY HH:mm:ss', 'DD/MM/YYYY HH:mmZZ'];
316 |
317 | constructor() { }
318 |
319 | }
320 | ```
321 |
322 | Both examples above will print `Last updated: 2017-01-01`
323 |
324 | ## amUtc pipe
325 |
326 | Enables UTC mode for subsequent moment operations (such as displaying the time in UTC).
327 |
328 | ``` typescript
329 | @Component({
330 | selector: 'app',
331 | template: `
332 | Last updated: {{ '2016-12-31T23:00:00.000-01:00' | amUtc | amDateFormat: 'YYYY-MM-DD' }}
333 | `
334 | })
335 | ```
336 |
337 | Prints `Last updated: 2017-01-01`
338 |
339 | ## amParseZone pipe
340 |
341 | Parses a string but keeps the resulting Moment object in a fixed-offset timezone with the provided offset in the string.
342 |
343 | ``` typescript
344 | @Component({
345 | selector: 'app',
346 | template: `
347 | Last updated: {{ '2016-12-31T23:00:00.000-03:00' | amParseZone | amDateFormat: 'LLLL (Z)' }}
348 | `
349 | })
350 | ```
351 |
352 | Prints `Last updated: Saturday, December 31, 2016 11:00 PM (-03:00)`
353 |
354 | ## amIsBefore and amIsAfter pipe
355 |
356 | Check if a moment is before another moment. Supports limiting granularity to a unit other than milliseconds, pass the units as second parameter
357 |
358 | ```typescript
359 | @Component({
360 | selector: 'app',
361 | template: `
362 | Today is before tomorrow: {{ today | amIsBefore:tomorrow:'day' }}
363 | `
364 | })
365 | ```
366 |
367 | Prints `Today is before tomorrow: true`
368 |
369 | ```typescript
370 | @Component({
371 | selector: 'app',
372 | template: `
373 | Tomorrow is after today: {{ tomorrow | amIsAfter:today:'day' }}
374 | `
375 | })
376 | ```
377 |
378 | Prints `Tomorrow is after today: true`
379 |
380 | NgxMomentOptions
381 | ----------------
382 | An `NgxMomentOptions` object can be provided to the module using the `forRoot` convention and will provide options for the pipes to use with the `moment` instance, these options are detailed in the table below:
383 |
384 | | prop | type | description |
385 | | --- |:---:| --- |
386 | | relativeTimeThresholdOptions | Dictionary
key: string
value: number | Provides the `relativeTimeThreshold` units allowing a pipe to set the `moment.relativeTimeThreshold` values.
The `key` is a unit defined as one of `ss`, `s`, `m`, `h`, `d`, `M`.
See [Relative Time Thresholds](https://momentjs.com/docs/#/customization/relative-time-threshold/) documentation for more details. |
387 |
388 | Complete Example
389 | ----------------
390 |
391 | ``` typescript
392 | import { NgModule, Component } from '@angular/core';
393 | import { BrowserModule } from '@angular/platform-browser';
394 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
395 | import { MomentModule } from 'ngx-moment';
396 |
397 | @Component({
398 | selector: 'app',
399 | template: `
400 | Last updated: {{myDate | amTimeAgo}}, {{myDate | amCalendar}}, {{myDate | amDateFormat:'LL'}}
401 | `
402 | })
403 | export class AppComponent {
404 | myDate: Date;
405 |
406 | constructor() {
407 | this.myDate = new Date();
408 | }
409 | }
410 |
411 | @NgModule({
412 | imports: [
413 | BrowserModule,
414 | MomentModule
415 | ],
416 | declarations: [ AppComponent ]
417 | bootstrap: [ AppComponent ]
418 | })
419 | class AppModule {}
420 |
421 | platformBrowserDynamic().bootstrapModule(AppModule);
422 | ```
423 |
424 | Demo
425 | ----
426 |
427 | [See online demo on StackBlitz](https://stackblitz.com/edit/ngx-moment-demo?file=src%2Fapp%2Fapp.component.html)
428 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "ngx-moment": {
7 | "projectType": "library",
8 | "root": "",
9 | "sourceRoot": "src",
10 | "prefix": "am",
11 | "architect": {
12 | "build": {
13 | "builder": "@angular-devkit/build-angular:ng-packagr",
14 | "options": {
15 | "project": "ng-package.json"
16 | },
17 | "configurations": {
18 | "production": {
19 | "tsConfig": "./tsconfig.json"
20 | }
21 | },
22 | "defaultConfiguration": "production"
23 | }
24 | }
25 | }
26 | },
27 | "defaultProject": "ngx-moment"
28 | }
29 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-preset-angular',
3 | setupFilesAfterEnv: ['/setupJest.ts'],
4 | };
5 |
--------------------------------------------------------------------------------
/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "dist/ngx-moment",
4 | "lib": {
5 | "entryFile": "src/index.ts"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/ng-package.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "dist/lib",
4 | "lib": {
5 | "entryFile": "src/index.ts"
6 | }
7 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngx-moment",
3 | "version": "6.0.2",
4 | "description": "Moment.JS pipes for Angular (timeago and more)",
5 | "scripts": {
6 | "build": "ng build",
7 | "test": "tslint --project tsconfig.lint.json && tsc -p tsconfig.spec.json && jest",
8 | "test:watch": "jest --watch",
9 | "test:coverage": "jest --coverage",
10 | "test:debug": "node --inspect-brk --inspect ./node_modules/jest/bin/jest.js --runInBand",
11 | "prepublish": "ng build",
12 | "prepare": "husky install",
13 | "postinstall": "husky install"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/urish/ngx-moment.git"
18 | },
19 | "keywords": [
20 | "angular",
21 | "timeago",
22 | "momentjs"
23 | ],
24 | "author": "Uri Shaked",
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/urish/ngx-moment/issues"
28 | },
29 | "homepage": "https://github.com/urish/ngx-moment#readme",
30 | "peerDependencies": {
31 | "moment": "^2.19.3"
32 | },
33 | "devDependencies": {
34 | "@angular-devkit/build-angular": "^13.1.1",
35 | "@angular/cli": "^13.1.1",
36 | "@angular/common": "^13.1.0",
37 | "@angular/compiler": "^13.1.0",
38 | "@angular/compiler-cli": "^13.1.0",
39 | "@angular/core": "^13.1.0",
40 | "@angular/language-service": "^13.1.0",
41 | "@angular/platform-browser": "^13.1.0",
42 | "@angular/platform-browser-dynamic": "^13.1.0",
43 | "@types/eslint": "^6.8.0",
44 | "@types/jest": "^27.0.3",
45 | "@types/node": "^16.11.13",
46 | "core-js": "^3.19.3",
47 | "husky": "^7.0.0",
48 | "jest": "^27.4.5",
49 | "jest-preset-angular": "^11.0.1",
50 | "lint-staged": "^12.1.2",
51 | "moment": "^2.29.1",
52 | "ng-packagr": "^13.1.1",
53 | "prettier": "^2.5.1",
54 | "rxjs": "^7.4.0",
55 | "tslib": "^2.3.1",
56 | "tslint": "^6.1.3",
57 | "typescript": "~4.4.4",
58 | "zone.js": "~0.11.4"
59 | },
60 | "husky": {
61 | "hooks": {
62 | "pre-commit": "lint-staged"
63 | }
64 | },
65 | "lint-staged": {
66 | "src/**/*.ts": [
67 | "tslint --project tsconfig.lint.json -c tslint.json --fix",
68 | "prettier --write",
69 | "git add"
70 | ]
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | printWidth: 100,
3 | singleQuote: true,
4 | tabWidth: 2,
5 | trailingComma: 'all',
6 | };
7 |
--------------------------------------------------------------------------------
/setupJest.ts:
--------------------------------------------------------------------------------
1 | import 'jest-preset-angular';
2 |
--------------------------------------------------------------------------------
/src/add.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import moment from 'moment';
3 | import { AddPipe } from './add.pipe';
4 |
5 | describe('AddPipe', () => {
6 | let pipe: AddPipe;
7 |
8 | beforeEach(() => (pipe = new AddPipe()));
9 |
10 | describe('#transform', () => {
11 | it('should throw when provided no arguments', () => {
12 | expect(() => (pipe.transform as any)(128)).toThrow('AddPipe: missing required arguments');
13 | });
14 |
15 | it('should add two hours', () => {
16 | const result = pipe.transform(moment('2016-01-24 15:00:00'), '2', 'hours');
17 | expect(moment(result).format('YYYY-MM-DD HH:mm:ss')).toBe('2016-01-24 17:00:00');
18 | });
19 |
20 | it('should add two days', () => {
21 | const result = pipe.transform(moment('2016-01-24 15:00:00'), '2', 'days');
22 | expect(moment(result).format('YYYY-MM-DD HH:mm:ss')).toBe('2016-01-26 15:00:00');
23 | });
24 |
25 | it('should add two years', () => {
26 | const result = pipe.transform(moment('2016-01-24 15:00:00'), '2', 'years');
27 | expect(moment(result).format('YYYY-MM-DD HH:mm:ss')).toBe('2018-01-24 15:00:00');
28 | });
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/add.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 | import moment from 'moment';
5 |
6 | @Pipe({ name: 'amAdd' })
7 | export class AddPipe implements PipeTransform {
8 | transform(
9 | value: moment.MomentInput,
10 | amount: moment.DurationInputArg1,
11 | unit?: moment.DurationInputArg2,
12 | ): any {
13 | if (
14 | typeof amount === 'undefined' ||
15 | (typeof amount === 'number' && typeof unit === 'undefined')
16 | ) {
17 | throw new Error('AddPipe: missing required arguments');
18 | }
19 | return moment(value).add(amount, unit);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/calendar.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import moment from 'moment';
3 | import { NgZone } from '@angular/core';
4 | import { CalendarPipe } from './calendar.pipe';
5 |
6 | class NgZoneMock {
7 | runOutsideAngular(fn: Function) {
8 | return fn();
9 | }
10 | run(fn: Function) {
11 | return fn();
12 | }
13 | }
14 |
15 | describe('CalendarPipe', () => {
16 | describe('#transform', () => {
17 | const pipe = new CalendarPipe(null, new NgZoneMock() as NgZone);
18 | it('should transform the start of the current day to "Today at 12:00 AM"', () => {
19 | expect(pipe.transform(moment().startOf('day'))).toBe('Today at 12:00 AM');
20 | });
21 |
22 | it('should transform the start of the current day to "Yesterday at 12:00 AM"', () => {
23 | const testDate = moment().startOf('day');
24 | const referenceTime = moment().clone().add(1, 'day');
25 | expect(pipe.transform(testDate, referenceTime)).toBe('Yesterday at 12:00 AM');
26 | });
27 |
28 | it('should transform date to "January 13th 2016, 1:23:45 AM"', () => {
29 | const testDate = new Date(2016, 0, 13, 1, 23, 45);
30 | const formats = { sameElse: 'MMMM Do YYYY, h:mm:ss A' };
31 | expect(pipe.transform(testDate, formats)).toBe('January 13th 2016, 1:23:45 AM');
32 | });
33 |
34 | it('should support any order of arguments', () => {
35 | const testDate = moment();
36 | const referenceTime = moment().clone().add(1, 'day');
37 | const formats = { lastDay: '[Last day at] h:mm A' };
38 | expect(pipe.transform(testDate, formats, referenceTime)).toBe(
39 | pipe.transform(testDate, referenceTime, formats),
40 | );
41 | });
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/src/calendar.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import {
4 | Pipe,
5 | ChangeDetectorRef,
6 | PipeTransform,
7 | EventEmitter,
8 | OnDestroy,
9 | NgZone,
10 | } from '@angular/core';
11 | import moment from 'moment';
12 | import { Subscription } from 'rxjs';
13 |
14 | @Pipe({ name: 'amCalendar', pure: false })
15 | export class CalendarPipe implements PipeTransform, OnDestroy {
16 | /**
17 | * Internal reference counter, so we can clean up when no instances are in use
18 | */
19 | private static refs = 0;
20 |
21 | private static timer: number | null = null;
22 | private static midnight: EventEmitter | null = null;
23 |
24 | private midnightSub: Subscription;
25 |
26 | constructor(private cdRef: ChangeDetectorRef, private ngZone: NgZone) {
27 | // using a single static timer for all instances of this pipe for performance reasons
28 | CalendarPipe.initTimer(ngZone);
29 |
30 | CalendarPipe.refs++;
31 |
32 | // values such as Today will need to be replaced with Yesterday after midnight,
33 | // so make sure we subscribe to an EventEmitter that we set up to emit at midnight
34 | this.midnightSub = CalendarPipe.midnight.subscribe(() => {
35 | this.ngZone.run(() => this.cdRef.markForCheck());
36 | });
37 | }
38 |
39 | transform(value: moment.MomentInput, ...args: any[]): any {
40 | let formats: any = null;
41 | let referenceTime: any = null;
42 |
43 | for (let i = 0, len = args.length; i < len; i++) {
44 | if (args[i] !== null) {
45 | if (typeof args[i] === 'object' && !moment.isMoment(args[i])) {
46 | formats = args[i];
47 | } else {
48 | referenceTime = moment(args[i]);
49 | }
50 | }
51 | }
52 |
53 | return moment(value).calendar(referenceTime, formats);
54 | }
55 |
56 | ngOnDestroy(): void {
57 | if (CalendarPipe.refs > 0) {
58 | CalendarPipe.refs--;
59 | }
60 |
61 | if (CalendarPipe.refs === 0) {
62 | CalendarPipe.removeTimer();
63 | }
64 |
65 | this.midnightSub.unsubscribe();
66 | }
67 |
68 | private static initTimer(ngZone: NgZone) {
69 | // initialize the timer
70 | if (!CalendarPipe.midnight) {
71 | CalendarPipe.midnight = new EventEmitter();
72 | if (typeof window !== 'undefined') {
73 | const timeToUpdate = CalendarPipe._getMillisecondsUntilUpdate();
74 | CalendarPipe.timer = ngZone.runOutsideAngular(() => {
75 | return window.setTimeout(() => {
76 | // emit the current date
77 | CalendarPipe.midnight.emit(new Date());
78 |
79 | // refresh the timer
80 | CalendarPipe.removeTimer();
81 | CalendarPipe.initTimer(ngZone);
82 | }, timeToUpdate);
83 | });
84 | }
85 | }
86 | }
87 |
88 | private static removeTimer() {
89 | if (CalendarPipe.timer) {
90 | window.clearTimeout(CalendarPipe.timer);
91 | CalendarPipe.timer = null;
92 | CalendarPipe.midnight = null;
93 | }
94 | }
95 |
96 | private static _getMillisecondsUntilUpdate() {
97 | const now = moment();
98 | const tomorrow = moment().startOf('day').add(1, 'days');
99 | const timeToMidnight = tomorrow.valueOf() - now.valueOf();
100 | return timeToMidnight + 1000; // 1 second after midnight
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/date-format.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { DateFormatPipe } from './date-format.pipe';
3 |
4 | describe('DateFormatPipe', () => {
5 | describe('#transform', () => {
6 | it('should properly format a date', () => {
7 | const pipe = new DateFormatPipe();
8 | const result = pipe.transform(moment('2016-01-24 01:23:45'), 'MMMM Do YYYY, h:mm:ss a');
9 | expect(result).toBe('January 24th 2016, 1:23:45 am');
10 | });
11 |
12 | it('should not format empty dates', () => {
13 | const pipe = new DateFormatPipe();
14 |
15 | const result1 = pipe.transform('', 'MMMM Do YYYY, h:mm:ss a');
16 | expect(result1).toBe('');
17 |
18 | const result2 = pipe.transform(null);
19 | expect(result2).toBe('');
20 |
21 | const result3 = pipe.transform(undefined);
22 | expect(result3).toBe('');
23 | });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/date-format.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 | import moment from 'moment';
5 |
6 | @Pipe({ name: 'amDateFormat' })
7 | export class DateFormatPipe implements PipeTransform {
8 | transform(value: moment.MomentInput, ...args: any[]): string {
9 | if (!value) {
10 | return '';
11 | }
12 | return moment(value).format(args[0]);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/difference.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import { DifferencePipe } from './difference.pipe';
2 |
3 | describe('DifferencePipe', () => {
4 | let pipe: DifferencePipe;
5 |
6 | beforeEach(() => (pipe = new DifferencePipe()));
7 |
8 | describe('#transform', () => {
9 | it('should take the difference of two dates in milliseconds', () => {
10 | const today = new Date(2012, 0, 22, 0, 0, 0);
11 | const testDate = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 13, 33, 33);
12 | expect(pipe.transform(testDate, today)).toBe(48813000);
13 | });
14 |
15 | it('should support passing "years", "months", "days", etc as a units parameter', () => {
16 | const test = new Date(2012, 0, 22, 4, 46, 54);
17 | const testDate1 = new Date(2013, 0, 22, 4, 46, 54);
18 | expect(pipe.transform(testDate1, test, 'years')).toBe(1);
19 | const testDate2 = new Date(2012, 1, 22, 4, 46, 54);
20 | expect(pipe.transform(testDate2, test, 'months')).toBe(1);
21 | const testDate3 = new Date(2012, 0, 23, 4, 46, 54);
22 | expect(pipe.transform(testDate3, test, 'days')).toBe(1);
23 | });
24 |
25 | it('should allow rounding to be disabled via parameter', () => {
26 | const test = new Date(2012, 0, 22, 4, 46, 54);
27 | const testDate1 = new Date(test.getFullYear() + 1, test.getMonth() + 6, test.getDate());
28 | expect(pipe.transform(testDate1, test, 'years')).toBe(1);
29 | expect(pipe.transform(testDate1, test, 'years', true)).toBeCloseTo(1.5, 1);
30 | });
31 |
32 | it('dates from the future should return negative values', () => {
33 | const today = new Date(2012, 0, 22, 4, 46, 54);
34 | const testDate = new Date(2013, 0, 22, 4, 46, 54);
35 | expect(String(pipe.transform(today, testDate))).toContain('-');
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/difference.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 | import moment from 'moment';
5 |
6 | @Pipe({ name: 'amDifference' })
7 | export class DifferencePipe implements PipeTransform {
8 | transform(
9 | value: moment.MomentInput,
10 | otherValue: moment.MomentInput,
11 | unit?: moment.unitOfTime.Diff,
12 | precision?: boolean,
13 | ): number {
14 | const date = moment(value);
15 | const date2 = otherValue !== null ? moment(otherValue) : moment();
16 |
17 | return date.diff(date2, unit, precision);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/duration.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import { DurationPipe } from './duration.pipe';
2 | import { NgxMomentOptions } from './moment-options';
3 |
4 | describe('DurationPipe', () => {
5 | let pipe: DurationPipe;
6 |
7 | beforeEach(() => (pipe = new DurationPipe()));
8 |
9 | describe('#transform', () => {
10 | it('should throw when provided no arguments', () => {
11 | expect(() => pipe.transform(128)).toThrow(
12 | 'DurationPipe: missing required time unit argument',
13 | );
14 | });
15 |
16 | it('should convert a duration to a human-readable string', () => {
17 | expect(pipe.transform(24, 'hours')).toEqual('a day');
18 | expect(pipe.transform(27, 'days')).toEqual('a month');
19 | expect(pipe.transform(365, 'seconds')).toEqual('6 minutes');
20 | expect(pipe.transform(365, 'days')).toEqual('a year');
21 | expect(pipe.transform(86400, 'seconds')).toEqual('a day');
22 | });
23 |
24 | it(`should convert '50 minutes' to 'an hour' with default 'relativeTimeThreshold'`, () => {
25 | expect(pipe.transform(50, 'minutes')).toEqual('an hour');
26 | });
27 | });
28 |
29 | describe('ctor with NgxMomentOptions', () => {
30 | const momentOptions: NgxMomentOptions = {
31 | relativeTimeThresholdOptions: {
32 | m: 59,
33 | },
34 | };
35 |
36 | beforeEach(() => (pipe = new DurationPipe(momentOptions)));
37 |
38 | it(`should convert '50 minutes' to '50 minutes' when relativeTimeThreshold for 'm' unit is set to 59`, () => {
39 | expect(pipe.transform(50, 'minutes')).toEqual('50 minutes');
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/duration.pipe.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 |
3 | import { Inject, Optional, Pipe, PipeTransform } from '@angular/core';
4 | import { NGX_MOMENT_OPTIONS, NgxMomentOptions } from './moment-options';
5 |
6 | @Pipe({ name: 'amDuration' })
7 | export class DurationPipe implements PipeTransform {
8 | allowedUnits: Array = ['ss', 's', 'm', 'h', 'd', 'M'];
9 |
10 | constructor(@Optional() @Inject(NGX_MOMENT_OPTIONS) momentOptions?: NgxMomentOptions) {
11 | this._applyOptions(momentOptions);
12 | }
13 |
14 | transform(value: moment.DurationInputArg1, ...args: string[]): string {
15 | if (typeof args === 'undefined' || args.length !== 1) {
16 | throw new Error('DurationPipe: missing required time unit argument');
17 | }
18 | return moment.duration(value, args[0] as moment.unitOfTime.DurationConstructor).humanize();
19 | }
20 |
21 | private _applyOptions(momentOptions: NgxMomentOptions): void {
22 | if (!momentOptions) {
23 | return;
24 | }
25 |
26 | if (!!momentOptions.relativeTimeThresholdOptions) {
27 | const units: Array = Object.keys(momentOptions.relativeTimeThresholdOptions);
28 | const filteredUnits: Array = units.filter(
29 | (unit) => this.allowedUnits.indexOf(unit) !== -1,
30 | );
31 | filteredUnits.forEach((unit) => {
32 | moment.relativeTimeThreshold(unit, momentOptions.relativeTimeThresholdOptions[unit]);
33 | });
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/from-unix.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { FromUnixPipe } from './from-unix.pipe';
3 |
4 | describe('FromUnixPipe', () => {
5 | describe('#transform', () => {
6 | it('should parse a unix timestamp number to moment', () => {
7 | const pipe = new FromUnixPipe();
8 | const result = pipe.transform(1456263980);
9 | expect(result).toEqual(moment.unix(1456263980));
10 | });
11 |
12 | it('should parse a unix timestamp string to moment', () => {
13 | const pipe = new FromUnixPipe();
14 | const result = pipe.transform('1456263980');
15 | expect(result).toEqual(moment.unix(1456263980));
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/from-unix.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 | import moment from 'moment';
5 |
6 | @Pipe({ name: 'amFromUnix' })
7 | export class FromUnixPipe implements PipeTransform {
8 | transform(value: number | string, ...args: string[]): any {
9 | return typeof value === 'string' ? moment.unix(parseInt(value, 10)) : moment.unix(value);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/from-utc.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { DateFormatPipe } from './date-format.pipe';
3 | import { FromUtcPipe } from './from-utc.pipe';
4 |
5 | describe('UtcPipe', () => {
6 | describe('#transform', () => {
7 | let utcDatePipe: FromUtcPipe;
8 |
9 | beforeEach(() => {
10 | utcDatePipe = new FromUtcPipe();
11 | });
12 |
13 | it('should output an invalid momemt object for a null input', () => {
14 | const utcDate = utcDatePipe.transform(null);
15 | expect(utcDate).toEqual(expect.any(moment));
16 | expect(utcDate.isValid()).toBe(false);
17 | });
18 |
19 | it('should output a moment object for a moment input', () => {
20 | const momentDate = moment();
21 | const utcDate = utcDatePipe.transform(momentDate);
22 | expect(utcDate).toEqual(expect.any(moment));
23 | expect(utcDate.isValid()).toBe(true);
24 | });
25 |
26 | it('should output a moment object for a date input', () => {
27 | const date = new Date();
28 | const utcDate = utcDatePipe.transform(date);
29 | expect(utcDate).toEqual(expect.any(moment));
30 | expect(utcDate.isValid()).toBe(true);
31 | });
32 |
33 | it('should output a moment object for a string date', () => {
34 | const dateString = '2016-01-01';
35 | const utcDate = utcDatePipe.transform(dateString);
36 | expect(utcDate).toEqual(expect.any(moment));
37 | expect(utcDate.isValid()).toBe(true);
38 | });
39 |
40 | it('should output a moment object for a timestamp', () => {
41 | const timestamp: number = Date.now();
42 | const utcDate = utcDatePipe.transform(timestamp);
43 | expect(utcDate).toEqual(expect.any(moment));
44 | expect(utcDate.isValid()).toBe(true);
45 | });
46 |
47 | it('should parse with provided timezone and format to UTC', () => {
48 | const amDateFormat = new DateFormatPipe();
49 | const datetimeString = '2016-12-31T23:00:00.000-01:00';
50 | const momentFormatString = 'YYYY-MM-DD';
51 | const utcOutput = utcDatePipe.transform(datetimeString);
52 | expect(amDateFormat.transform(utcOutput, momentFormatString)).toEqual('2017-01-01');
53 | });
54 |
55 | it('should parse as UTC without provided timezone', () => {
56 | const amDateFormat = new DateFormatPipe();
57 | const datetimeString = '2016-12-31T23:00:00.000';
58 | const momentFormatString = 'YYYY-MM-DD';
59 | const utcOutput = utcDatePipe.transform(datetimeString);
60 | expect(amDateFormat.transform(utcOutput, momentFormatString)).toEqual('2016-12-31');
61 | });
62 |
63 | it('should parse as UTC with a provided format', () => {
64 | const datetimeString = '31/12/2016, 23:02:00';
65 | const momentFormatString = 'DD/MM/YYYY, HH:mm:ss';
66 | const utcOutput = utcDatePipe.transform(datetimeString, momentFormatString);
67 | expect(utcOutput).toEqual(expect.any(moment));
68 | expect(utcOutput.isValid()).toBe(true);
69 |
70 | expect(utcOutput.year()).toBe(2016);
71 | expect(utcOutput.month()).toBe(11);
72 | expect(utcOutput.date()).toBe(31);
73 | });
74 |
75 | it('should parse as UTC with an array of provided formats', () => {
76 | const datetimeString = '31st 12/2016';
77 | const momentFormatStrings = ['DD/MM/YYYY, HH:mm:ss', 'Do MM/YYYY'];
78 | const utcOutput = utcDatePipe.transform(datetimeString, momentFormatStrings);
79 | expect(utcOutput).toEqual(expect.any(moment));
80 | expect(utcOutput.isValid()).toBe(true);
81 |
82 | expect(utcOutput.year()).toBe(2016);
83 | expect(utcOutput.month()).toBe(11);
84 | expect(utcOutput.date()).toBe(31);
85 | });
86 |
87 | it('should output an invalid moment object for a different formatted input', () => {
88 | const datetimeString = '31/12/2016, 23:02:00';
89 | const utcDate = utcDatePipe.transform(datetimeString);
90 | expect(utcDate).toEqual(expect.any(moment));
91 | expect(utcDate.isValid()).toBe(false);
92 | });
93 | });
94 | });
95 |
--------------------------------------------------------------------------------
/src/from-utc.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 | import moment from 'moment';
5 |
6 | @Pipe({ name: 'amFromUtc' })
7 | export class FromUtcPipe implements PipeTransform {
8 | transform(value: moment.MomentInput, formats?: string | string[], ...args: string[]): any {
9 | return formats ? moment.utc(value, formats) : moment.utc(value);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { AddPipe } from './add.pipe';
2 | export { CalendarPipe } from './calendar.pipe';
3 | export { DateFormatPipe } from './date-format.pipe';
4 | export { DifferencePipe } from './difference.pipe';
5 | export { DurationPipe } from './duration.pipe';
6 | export { FromUnixPipe } from './from-unix.pipe';
7 | export { ParsePipe } from './parse.pipe';
8 | export { MomentModule } from './moment.module';
9 | export { SubtractPipe } from './subtract.pipe';
10 | export { TimeAgoPipe } from './time-ago.pipe';
11 | export { UtcPipe } from './utc.pipe';
12 | export { FromUtcPipe } from './from-utc.pipe';
13 | export { LocalTimePipe } from './local.pipe';
14 | export { LocalePipe } from './locale.pipe';
15 | export { ParseZonePipe } from './parse-zone.pipe';
16 | export { IsBeforePipe } from './is-before.pipe';
17 | export { IsAfterPipe } from './is-after.pipe';
18 |
19 | export { NgxMomentOptions, NGX_MOMENT_OPTIONS } from './moment-options';
20 |
--------------------------------------------------------------------------------
/src/is-after.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-variable */
2 | import { IsAfterPipe } from './is-after.pipe';
3 |
4 | describe('IsAfterPipe', () => {
5 | let pipe: IsAfterPipe;
6 |
7 | beforeEach(() => (pipe = new IsAfterPipe()));
8 |
9 | describe('#transform', () => {
10 | it('should return true if value is after otherValue', () => {
11 | const test = new Date(2018, 11, 15, 0, 0, 0);
12 | const testDate1 = new Date(2018, 11, 13, 0, 0, 0);
13 | expect(pipe.transform(test, testDate1)).toBeTruthy();
14 | });
15 |
16 | it('should support passing "year", "month", "week", "day", etc as a unit parameter', () => {
17 | const test = new Date(2019, 11, 13, 12, 45, 45);
18 | const testDate1 = new Date(2018, 0, 13, 12, 45, 45);
19 | expect(pipe.transform(test, testDate1, 'year')).toBe(true);
20 | const testDate2 = new Date(2018, 1, 13, 12, 45, 45);
21 | expect(pipe.transform(test, testDate2, 'month')).toBe(true);
22 | const testDate3 = new Date(2018, 1, 10, 12, 45, 45);
23 | expect(pipe.transform(test, testDate3, 'day')).toBe(true);
24 | });
25 |
26 | it('should return false if value is before otherValue', () => {
27 | const test = new Date(2018, 11, 13, 0, 0, 0);
28 | const testDate1 = new Date(2018, 11, 15, 0, 0, 0);
29 | expect(pipe.transform(test, testDate1)).toBeFalsy();
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/is-after.pipe.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 |
5 | @Pipe({
6 | name: 'amIsAfter',
7 | })
8 | export class IsAfterPipe implements PipeTransform {
9 | transform(
10 | value: moment.MomentInput,
11 | otherValue: moment.MomentInput,
12 | unit?: moment.unitOfTime.StartOf,
13 | ): boolean {
14 | return moment(value).isAfter(moment(otherValue), unit);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/is-before.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import { IsBeforePipe } from './is-before.pipe';
2 |
3 | describe('IsBeforePipe', () => {
4 | let pipe: IsBeforePipe;
5 |
6 | beforeEach(() => (pipe = new IsBeforePipe()));
7 |
8 | describe('#transform', () => {
9 | it('should return true if value is before otherValue', () => {
10 | const test = new Date(2018, 11, 13, 0, 0, 0);
11 | const testDate1 = new Date(2018, 11, 15, 0, 0, 0);
12 | expect(pipe.transform(test, testDate1)).toBeTruthy();
13 | });
14 |
15 | it('should support passing "year", "month", "week", "day", etc as a unit parameter', () => {
16 | const test = new Date(2018, 0, 13, 12, 45, 45);
17 | const testDate1 = new Date(2019, 0, 13, 12, 45, 45);
18 | expect(pipe.transform(test, testDate1, 'year')).toBe(true);
19 | const testDate2 = new Date(2018, 1, 13, 12, 45, 45);
20 | expect(pipe.transform(test, testDate2, 'month')).toBe(true);
21 | const testDate3 = new Date(2018, 1, 13, 12, 45, 45);
22 | expect(pipe.transform(test, testDate3, 'day')).toBe(true);
23 | });
24 |
25 | it('should return false if value is after otherValue', () => {
26 | const test = new Date(2018, 11, 15, 0, 0, 0);
27 | const testDate1 = new Date(2018, 11, 13, 0, 0, 0);
28 | expect(pipe.transform(test, testDate1)).toBeFalsy();
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/is-before.pipe.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 |
5 | @Pipe({
6 | name: 'amIsBefore',
7 | })
8 | export class IsBeforePipe implements PipeTransform {
9 | transform(
10 | value: moment.MomentInput,
11 | otherValue: moment.MomentInput,
12 | unit?: moment.unitOfTime.StartOf,
13 | ): boolean {
14 | return moment(value).isBefore(moment(otherValue), unit);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/local.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { DateFormatPipe } from './date-format.pipe';
3 | import { LocalTimePipe } from './local.pipe';
4 |
5 | describe('LocalPipe', () => {
6 | describe('#transform', () => {
7 | let localPipe: LocalTimePipe;
8 |
9 | beforeEach(() => {
10 | localPipe = new LocalTimePipe();
11 | });
12 |
13 | it('should output an invalid momemt object for a null input', () => {
14 | const localDate = localPipe.transform(null);
15 | expect(localDate).toEqual(expect.any(moment));
16 | expect(localDate.isValid()).toBe(false);
17 | });
18 |
19 | it('should output a moment object for a moment input', () => {
20 | const momentDate = moment();
21 | const localDate = localPipe.transform(momentDate);
22 | expect(localDate).toEqual(expect.any(moment));
23 | expect(localDate.isValid()).toBe(true);
24 | });
25 |
26 | it('should output a moment object for a date input', () => {
27 | const date = new Date();
28 | const localDate = localPipe.transform(date);
29 | expect(localDate).toEqual(expect.any(moment));
30 | expect(localDate.isValid()).toBe(true);
31 | });
32 |
33 | it('should output a moment object for a string date', () => {
34 | const dateString = '2016-01-01';
35 | const localDate = localPipe.transform(dateString);
36 | expect(localDate).toEqual(expect.any(moment));
37 | expect(localDate.isValid()).toBe(true);
38 | });
39 |
40 | it('should output a moment object for a timestamp', () => {
41 | const timestamp: number = Date.now();
42 | const localDate = localPipe.transform(timestamp);
43 | expect(localDate).toEqual(expect.any(moment));
44 | expect(localDate.isValid()).toBe(true);
45 | });
46 |
47 | it('should be pipeable to amDateFormat', () => {
48 | const amDateFormat = new DateFormatPipe();
49 | const datetimeString = '2015-12-31T23:00:00.000-15:00';
50 | const momentFormatString = 'YYYY-MM';
51 | const localOutput = localPipe.transform(datetimeString);
52 | expect(amDateFormat.transform(localOutput, momentFormatString)).toEqual('2016-01');
53 | });
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/src/local.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import moment from 'moment';
3 |
4 | @Pipe({ name: 'amLocal' })
5 | export class LocalTimePipe implements PipeTransform {
6 | transform(value: moment.MomentInput): moment.Moment {
7 | return moment(value).local();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/locale.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { DateFormatPipe } from './date-format.pipe';
3 | import { LocalePipe } from './locale.pipe';
4 |
5 | describe('LocalePipe', () => {
6 | describe('#transform', () => {
7 | let localePipe: LocalePipe;
8 |
9 | beforeEach(() => {
10 | localePipe = new LocalePipe();
11 | });
12 |
13 | it('should output a moment object for a string date', () => {
14 | const datetimeString = '2016-01-24 01:23:45';
15 | const langKeyString1 = 'en';
16 | const langKeyString2 = 'de';
17 | const parsedMoment1 = localePipe.transform(datetimeString, langKeyString1);
18 | const parsedMoment2 = localePipe.transform(datetimeString, langKeyString2);
19 | expect(parsedMoment1).toEqual(expect.any(moment));
20 | expect(parsedMoment2).toEqual(expect.any(moment));
21 | expect(parsedMoment1.isValid()).toBe(true);
22 | expect(parsedMoment2.isValid()).toBe(true);
23 | });
24 |
25 | it('should be pipeable to amDateFormat', () => {
26 | const amDateFormat = new DateFormatPipe();
27 | const datetimeString = '2016-01-24 14:23:45';
28 | const langKeyString1 = 'en';
29 | const langKeyString2 = 'de';
30 | const momentFormatString1 = 'MMMM Do YYYY, h:mm:ss a';
31 | const momentFormatString2 = 'MMMM Do YYYY, HH:mm:ss';
32 | const parseOutput1 = localePipe.transform(datetimeString, langKeyString1);
33 | const parseOutput2 = localePipe.transform(datetimeString, langKeyString2);
34 | expect(amDateFormat.transform(parseOutput1, momentFormatString1)).toEqual(
35 | 'January 24th 2016, 2:23:45 pm',
36 | );
37 | expect(amDateFormat.transform(parseOutput2, momentFormatString2)).toEqual(
38 | 'Januar 24. 2016, 14:23:45',
39 | );
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/locale.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import moment from 'moment';
3 |
4 | @Pipe({ name: 'amLocale' })
5 | export class LocalePipe implements PipeTransform {
6 | transform(value: moment.MomentInput, locale: string): moment.Moment {
7 | return moment(value).locale(locale);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/moment-options.ts:
--------------------------------------------------------------------------------
1 | import { InjectionToken } from '@angular/core';
2 |
3 | export const NGX_MOMENT_OPTIONS: InjectionToken = new InjectionToken<
4 | NgxMomentOptions
5 | >('NGX_MOMENT_OPTIONS');
6 |
7 | export interface NgxMomentOptions {
8 | /**
9 | * relativeTimeThresholdOptions
10 | * @description Provides the `relativeTimeThreshold` units allowing a pipe to set the `moment.relativeTimeThreshold` values.
11 | * The `key` is a unit defined as one of `ss`, `s`, `m`, `h`, `d`, `M`.
12 | * @see https://momentjs.com/docs/#/customization/relative-time-threshold/
13 | * @example by default more than 45 seconds is considered a minute, more than 22 hours is considered a day and so on.
14 | * So settings the unit 'm' to `59` will adjust the `relativeTimeThreshold` and consider more than 59 minutes
15 | * to be an hour (default is `45 minutes`)
16 | */
17 | relativeTimeThresholdOptions: { [key: string]: number };
18 | }
19 |
--------------------------------------------------------------------------------
/src/moment.module.ts:
--------------------------------------------------------------------------------
1 | import { ModuleWithProviders, NgModule } from '@angular/core';
2 | import { NGX_MOMENT_OPTIONS, NgxMomentOptions } from './moment-options';
3 |
4 | import { AddPipe } from './add.pipe';
5 | import { CalendarPipe } from './calendar.pipe';
6 | import { DateFormatPipe } from './date-format.pipe';
7 | import { DifferencePipe } from './difference.pipe';
8 | import { DurationPipe } from './duration.pipe';
9 | import { FromUnixPipe } from './from-unix.pipe';
10 | import { FromUtcPipe } from './from-utc.pipe';
11 | import { IsAfterPipe } from './is-after.pipe';
12 | import { IsBeforePipe } from './is-before.pipe';
13 | import { LocalTimePipe } from './local.pipe';
14 | import { LocalePipe } from './locale.pipe';
15 | import { ParsePipe } from './parse.pipe';
16 | import { ParseZonePipe } from './parse-zone.pipe';
17 | import { SubtractPipe } from './subtract.pipe';
18 | import { TimeAgoPipe } from './time-ago.pipe';
19 | import { UtcPipe } from './utc.pipe';
20 |
21 | const ANGULAR_MOMENT_PIPES = [
22 | AddPipe,
23 | CalendarPipe,
24 | DateFormatPipe,
25 | DifferencePipe,
26 | DurationPipe,
27 | FromUnixPipe,
28 | ParsePipe,
29 | SubtractPipe,
30 | TimeAgoPipe,
31 | UtcPipe,
32 | FromUtcPipe,
33 | LocalTimePipe,
34 | LocalePipe,
35 | ParseZonePipe,
36 | IsBeforePipe,
37 | IsAfterPipe,
38 | ];
39 |
40 | @NgModule({
41 | declarations: ANGULAR_MOMENT_PIPES,
42 | exports: ANGULAR_MOMENT_PIPES,
43 | })
44 | export class MomentModule {
45 | static forRoot(options?: NgxMomentOptions): ModuleWithProviders {
46 | return {
47 | ngModule: MomentModule,
48 | providers: [
49 | {
50 | provide: NGX_MOMENT_OPTIONS,
51 | useValue: {
52 | ...options,
53 | },
54 | },
55 | ],
56 | };
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/parse-zone.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { ParseZonePipe } from './parse-zone.pipe';
3 |
4 | describe('ParseZonePipe', () => {
5 | describe('#transform', () => {
6 | let parseZonePipe: ParseZonePipe;
7 |
8 | beforeEach(() => {
9 | parseZonePipe = new ParseZonePipe();
10 | });
11 |
12 | it('should output an invalid momemt object for a null input', () => {
13 | const parsedDate = parseZonePipe.transform(null);
14 | expect(parsedDate).toEqual(expect.any(moment));
15 | expect(parsedDate.isValid()).toBe(false);
16 | });
17 |
18 | it('should parse a date in ISO_8601 format', () => {
19 | const date: string = moment().toISOString();
20 | const parsedDate = parseZonePipe.transform(date);
21 | expect(parsedDate).toEqual(expect.any(moment));
22 | expect(parsedDate.isValid()).toBe(true);
23 | });
24 |
25 | it('should preserve a positive UTC offset', () => {
26 | const offset = 720;
27 | const date = moment().utcOffset(offset).format();
28 | const parsedDate = parseZonePipe.transform(date);
29 | expect(parsedDate.utcOffset()).toEqual(offset);
30 | });
31 |
32 | it('should preserve a negative UTC offset', () => {
33 | const offset = -720;
34 | const date = moment().utcOffset(offset).format();
35 | const parsedDate = parseZonePipe.transform(date);
36 | expect(parsedDate.utcOffset()).toEqual(offset);
37 | });
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/src/parse-zone.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import moment from 'moment';
3 |
4 | @Pipe({ name: 'amParseZone' })
5 | export class ParseZonePipe implements PipeTransform {
6 | transform(value: moment.MomentInput): moment.Moment {
7 | return moment.parseZone(value);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/parse.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { DateFormatPipe } from './date-format.pipe';
3 | import { ParsePipe } from './parse.pipe';
4 |
5 | describe('ParsePipe', () => {
6 | describe('#transform', () => {
7 | let parsePipe: ParsePipe;
8 |
9 | beforeEach(() => {
10 | parsePipe = new ParsePipe();
11 | });
12 |
13 | it('should output a moment object for a string date', () => {
14 | const dateString = '2015#09#13';
15 | const formatInputString = 'YYYY#MM#DD';
16 | const parsedMoment = parsePipe.transform(dateString, formatInputString);
17 | expect(parsedMoment).toEqual(expect.any(moment));
18 | expect(parsedMoment.isValid()).toBe(true);
19 |
20 | expect(parsedMoment.year()).toBe(2015);
21 | expect(parsedMoment.month()).toBe(8);
22 | expect(parsedMoment.date()).toBe(13);
23 | });
24 |
25 | it('should be pipeable to amDateFormat', () => {
26 | const amDateFormat = new DateFormatPipe();
27 | const datetimeString = '01/02/2016';
28 | const formatInputString = 'DD/MM/YYYY';
29 | const momentFormatString = 'YYYY-MM-DD';
30 | const parseOutput = parsePipe.transform(datetimeString, formatInputString);
31 | expect(amDateFormat.transform(parseOutput, momentFormatString)).toEqual('2016-02-01');
32 | });
33 |
34 | it('should output a moment object for a string date with array of formats', () => {
35 | const dateString = '15--09//13';
36 | const formatInputStrings = ['YYYY#MM#DD', 'YY--MM//DD'];
37 | const parsedMoment = parsePipe.transform(dateString, formatInputStrings);
38 | expect(parsedMoment).toEqual(expect.any(moment));
39 | expect(parsedMoment.isValid()).toBe(true);
40 |
41 | expect(parsedMoment.year()).toBe(2015);
42 | expect(parsedMoment.month()).toBe(8);
43 | expect(parsedMoment.date()).toBe(13);
44 | });
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/src/parse.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import moment from 'moment';
3 |
4 | @Pipe({ name: 'amParse' })
5 | export class ParsePipe implements PipeTransform {
6 | transform(value: moment.MomentInput, formats: string | string[]): moment.Moment {
7 | return moment(value, formats);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/subtract.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { SubtractPipe } from './subtract.pipe';
3 |
4 | describe('SubtractPipe', () => {
5 | let pipe: SubtractPipe;
6 |
7 | beforeEach(() => (pipe = new SubtractPipe()));
8 |
9 | describe('#transform', () => {
10 | it('should throw when provided no arguments', () => {
11 | expect(() => (pipe.transform as any)(128)).toThrow(
12 | 'SubtractPipe: missing required arguments',
13 | );
14 | });
15 |
16 | it('should subtract two hours', () => {
17 | const result = pipe.transform(moment('2016-01-24 15:00:00'), '2', 'hours');
18 | expect(moment(result).format('YYYY-MM-DD HH:mm:ss')).toBe('2016-01-24 13:00:00');
19 | });
20 |
21 | it('should subtract two days', () => {
22 | const result = pipe.transform(moment('2016-01-24 15:00:00'), '2', 'days');
23 | expect(moment(result).format('YYYY-MM-DD HH:mm:ss')).toBe('2016-01-22 15:00:00');
24 | });
25 |
26 | it('should subtract two years', () => {
27 | const result = pipe.transform(moment('2016-01-24 15:00:00'), '2', 'years');
28 | expect(moment(result).format('YYYY-MM-DD HH:mm:ss')).toBe('2014-01-24 15:00:00');
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/subtract.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import { Pipe, PipeTransform } from '@angular/core';
4 | import moment from 'moment';
5 |
6 | @Pipe({ name: 'amSubtract' })
7 | export class SubtractPipe implements PipeTransform {
8 | transform(
9 | value: moment.MomentInput,
10 | amount: moment.DurationInputArg1,
11 | unit?: moment.DurationInputArg2,
12 | ): any {
13 | if (
14 | typeof amount === 'undefined' ||
15 | (typeof amount === 'number' && typeof unit === 'undefined')
16 | ) {
17 | throw new Error('SubtractPipe: missing required arguments');
18 | }
19 | return moment(value).subtract(amount, unit);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/time-ago.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import { NgZone } from '@angular/core';
2 | import { TimeAgoPipe } from './time-ago.pipe';
3 | import moment from 'moment';
4 | import 'moment/min/locales';
5 |
6 | declare var global: any;
7 |
8 | jest.useFakeTimers();
9 |
10 | class NgZoneMock {
11 | runOutsideAngular(fn: Function) {
12 | return fn();
13 | }
14 | run(fn: Function) {
15 | return fn();
16 | }
17 | }
18 |
19 | const _Date = Date;
20 |
21 | function fakeDate(defaultDate: string | number) {
22 | global.Date = function (arg: any) {
23 | return new _Date(typeof arg !== 'undefined' ? arg : defaultDate);
24 | };
25 | global.Date.UTC = _Date.UTC;
26 | }
27 |
28 | describe('TimeAgoPipe', () => {
29 | describe('#transform', () => {
30 | beforeEach(() => {
31 | moment.locale('en-gb');
32 | });
33 |
34 | afterEach(() => {
35 | global.Date = _Date;
36 | jest.clearAllTimers();
37 | });
38 |
39 | it('should transform the current date to "a few seconds ago"', () => {
40 | const pipe = new TimeAgoPipe(null, new NgZoneMock() as NgZone);
41 | expect(pipe.transform(new Date())).toBe('a few seconds ago');
42 | });
43 |
44 | it('should support string dates', () => {
45 | const pipe = new TimeAgoPipe(null, new NgZoneMock() as NgZone);
46 | const dateStr = new Date().toISOString();
47 | expect(pipe.transform(dateStr)).toBe('a few seconds ago');
48 | });
49 |
50 | it('should omit the suffix if second parameter is truthy', () => {
51 | const pipe = new TimeAgoPipe(null, new NgZoneMock() as NgZone);
52 | expect(pipe.transform(new Date(new Date().getTime() + 60000), true)).toBe('a minute');
53 | });
54 |
55 | it('should automatically update the text as time passes', () => {
56 | const changeDetectorMock = { markForCheck: jest.fn() };
57 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
58 | expect(pipe.transform(new Date())).toBe('a few seconds ago');
59 | expect(changeDetectorMock.markForCheck).not.toHaveBeenCalled();
60 | jest.advanceTimersByTime(60000);
61 | expect(changeDetectorMock.markForCheck).toHaveBeenCalled();
62 | });
63 |
64 | it('should update the text with a new date instance different from the previous one', () => {
65 | const changeDetectorMock = { markForCheck: jest.fn() };
66 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
67 | fakeDate('2016-05-01');
68 | expect(pipe.transform(new Date())).toBe('a few seconds ago');
69 | expect(pipe.transform(new Date(0))).toBe('46 years ago');
70 | expect(pipe.transform(moment())).toBe('a few seconds ago');
71 | expect(pipe.transform(moment(0))).toBe('46 years ago');
72 | });
73 |
74 | it('should update the text when moment locale changes', () => {
75 | const changeDetectorMock = { markForCheck: jest.fn() };
76 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
77 | fakeDate('2016-05-01');
78 | expect(pipe.transform(moment(0))).toBe('46 years ago');
79 | expect(pipe.transform(moment(0).locale('pl'))).toBe('46 lat temu');
80 | });
81 |
82 | it('should reset language when localized moment changes to Date', () => {
83 | const changeDetectorMock = { markForCheck: jest.fn() };
84 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
85 | fakeDate('2016-05-01');
86 | expect(pipe.transform(moment(0).locale('pl'))).toBe('46 lat temu');
87 | expect(pipe.transform(new Date(0))).toBe('46 years ago');
88 | });
89 |
90 | it('should update the text when using Date Objects and locale changes', () => {
91 | const changeDetectorMock = { markForCheck: jest.fn() };
92 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
93 | fakeDate('2016-05-01');
94 | expect(pipe.transform(new Date(0))).toBe('46 years ago');
95 | moment.locale('de');
96 | expect(pipe.transform(new Date(0))).toBe('vor 46 Jahren');
97 | });
98 |
99 | it('should update the text when the date instance time is updated', () => {
100 | const changeDetectorMock = { markForCheck: jest.fn() };
101 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
102 | fakeDate('2016-05-01');
103 | const date = new Date();
104 | expect(pipe.transform(date)).toBe('a few seconds ago');
105 | date.setFullYear(2000);
106 | expect(pipe.transform(date)).toBe('16 years ago');
107 |
108 | const dateAsMoment = moment();
109 | expect(pipe.transform(dateAsMoment)).toBe('a few seconds ago');
110 | dateAsMoment.year(2000);
111 | expect(pipe.transform(dateAsMoment)).toBe('16 years ago');
112 | });
113 |
114 | it('should remove all timers when destroyed', () => {
115 | const changeDetectorMock = { markForCheck: jest.fn() };
116 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
117 | expect(pipe.transform(new Date())).toBe('a few seconds ago');
118 | pipe.ngOnDestroy();
119 | jest.advanceTimersByTime(60000);
120 | expect(changeDetectorMock.markForCheck).not.toHaveBeenCalled();
121 | });
122 |
123 | it('should transform a date to a different format when a format function is provided', () => {
124 | const changeDetectorMock = { markForCheck: jest.fn() };
125 | const formatFnMock = (m: moment.Moment) => {
126 | const seconds = m.diff(moment()) / 1000;
127 | return seconds >= 3600 ? '' : `${Math.floor(seconds / 60)} min ago`;
128 | };
129 | const pipe = new TimeAgoPipe(changeDetectorMock as any, new NgZoneMock() as NgZone);
130 | fakeDate('2016-05-01');
131 | expect(pipe.transform(moment().add(20, 'm'), false, formatFnMock)).toBe('20 min ago');
132 | expect(pipe.transform(moment().add(1, 'h'), false, formatFnMock)).toBe('');
133 | expect(pipe.transform(moment().add(3, 'h'), false, formatFnMock)).toBe('');
134 | });
135 | });
136 | });
137 |
--------------------------------------------------------------------------------
/src/time-ago.pipe.ts:
--------------------------------------------------------------------------------
1 | /* ngx-moment (c) 2015, 2016 Uri Shaked / MIT Licence */
2 |
3 | import { Pipe, ChangeDetectorRef, PipeTransform, OnDestroy, NgZone } from '@angular/core';
4 | import moment from 'moment';
5 |
6 | @Pipe({ name: 'amTimeAgo', pure: false })
7 | export class TimeAgoPipe implements PipeTransform, OnDestroy {
8 | private currentTimer: number | null;
9 |
10 | private lastTime: Number;
11 | private lastValue: moment.MomentInput;
12 | private lastOmitSuffix: boolean;
13 | private lastLocale?: string;
14 | private lastText: string;
15 | private formatFn: (m: moment.Moment) => string;
16 |
17 | constructor(private cdRef: ChangeDetectorRef, private ngZone: NgZone) {}
18 |
19 | format(m: moment.Moment) {
20 | return m.from(moment(), this.lastOmitSuffix);
21 | }
22 |
23 | transform(
24 | value: moment.MomentInput,
25 | omitSuffix?: boolean,
26 | formatFn?: (m: moment.Moment) => string,
27 | ): string {
28 | if (this.hasChanged(value, omitSuffix)) {
29 | this.lastTime = this.getTime(value);
30 | this.lastValue = value;
31 | this.lastOmitSuffix = omitSuffix;
32 | this.lastLocale = this.getLocale(value);
33 | this.formatFn = formatFn || this.format.bind(this);
34 | this.removeTimer();
35 | this.createTimer();
36 | this.lastText = this.formatFn(moment(value));
37 | } else {
38 | this.createTimer();
39 | }
40 |
41 | return this.lastText;
42 | }
43 |
44 | ngOnDestroy(): void {
45 | this.removeTimer();
46 | }
47 |
48 | private createTimer() {
49 | if (this.currentTimer) {
50 | return;
51 | }
52 |
53 | const momentInstance = moment(this.lastValue);
54 | const timeToUpdate = this.getSecondsUntilUpdate(momentInstance) * 1000;
55 |
56 | this.currentTimer = this.ngZone.runOutsideAngular(() => {
57 | if (typeof window !== 'undefined') {
58 | return window.setTimeout(() => {
59 | this.lastText = this.formatFn(moment(this.lastValue));
60 |
61 | this.currentTimer = null;
62 | this.ngZone.run(() => this.cdRef.markForCheck());
63 | }, timeToUpdate);
64 | } else {
65 | return null;
66 | }
67 | });
68 | }
69 |
70 | private removeTimer() {
71 | if (this.currentTimer) {
72 | window.clearTimeout(this.currentTimer);
73 | this.currentTimer = null;
74 | }
75 | }
76 |
77 | private getSecondsUntilUpdate(momentInstance: moment.Moment) {
78 | const howOld = Math.abs(moment().diff(momentInstance, 'minute'));
79 | if (howOld < 1) {
80 | return 1;
81 | } else if (howOld < 60) {
82 | return 30;
83 | } else if (howOld < 180) {
84 | return 300;
85 | } else {
86 | return 3600;
87 | }
88 | }
89 |
90 | private hasChanged(value: moment.MomentInput, omitSuffix?: boolean): boolean {
91 | return (
92 | this.getTime(value) !== this.lastTime ||
93 | this.getLocale(value) !== this.lastLocale ||
94 | omitSuffix !== this.lastOmitSuffix
95 | );
96 | }
97 |
98 | private getTime(value: moment.MomentInput): number {
99 | if (moment.isDate(value)) {
100 | return value.getTime();
101 | } else if (moment.isMoment(value)) {
102 | return value.valueOf();
103 | } else {
104 | return moment(value).valueOf();
105 | }
106 | }
107 |
108 | private getLocale(value: moment.MomentInput): string | null {
109 | return moment.isMoment(value) ? value.locale() : moment.locale();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/utc.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 | import { DateFormatPipe } from './date-format.pipe';
3 | import { UtcPipe } from './utc.pipe';
4 |
5 | describe('UtcPipe', () => {
6 | describe('#transform', () => {
7 | let utcDatePipe: UtcPipe;
8 |
9 | beforeEach(() => {
10 | utcDatePipe = new UtcPipe();
11 | });
12 |
13 | it('should output an invalid momemt object for a null input', () => {
14 | const utcDate = utcDatePipe.transform(null);
15 | expect(utcDate).toEqual(expect.any(moment));
16 | expect(utcDate.isValid()).toBe(false);
17 | });
18 |
19 | it('should output a moment object for a moment input', () => {
20 | const momentDate = moment();
21 | const utcDate = utcDatePipe.transform(momentDate);
22 | expect(utcDate).toEqual(expect.any(moment));
23 | expect(utcDate.isValid()).toBe(true);
24 | });
25 |
26 | it('should output a moment object for a date input', () => {
27 | const date = new Date();
28 | const utcDate = utcDatePipe.transform(date);
29 | expect(utcDate).toEqual(expect.any(moment));
30 | expect(utcDate.isValid()).toBe(true);
31 | });
32 |
33 | it('should output a moment object for a string date', () => {
34 | const dateString = '2016-01-01';
35 | const utcDate = utcDatePipe.transform(dateString);
36 | expect(utcDate).toEqual(expect.any(moment));
37 | expect(utcDate.isValid()).toBe(true);
38 | });
39 |
40 | it('should output a moment object for a timestamp', () => {
41 | const timestamp: number = Date.now();
42 | const utcDate = utcDatePipe.transform(timestamp);
43 | expect(utcDate).toEqual(expect.any(moment));
44 | expect(utcDate.isValid()).toBe(true);
45 | });
46 |
47 | it('should be pipeable to amDateFormat', () => {
48 | const amDateFormat = new DateFormatPipe();
49 | const datetimeString = '2015-12-31T23:00:00.000-01:00';
50 | const momentFormatString = 'YYYY-MM-DD';
51 | const utcOutput = utcDatePipe.transform(datetimeString);
52 | expect(amDateFormat.transform(utcOutput, momentFormatString)).toEqual('2016-01-01');
53 | });
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/src/utc.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import moment from 'moment';
3 |
4 | @Pipe({ name: 'amUtc' })
5 | export class UtcPipe implements PipeTransform {
6 | transform(value: moment.MomentInput): moment.Moment {
7 | return moment(value).utc();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "strict": true,
9 | "strictNullChecks": false,
10 | "noImplicitOverride": true,
11 | "noPropertyAccessFromIndexSignature": true,
12 | "noImplicitReturns": true,
13 | "noFallthroughCasesInSwitch": true,
14 | "sourceMap": true,
15 | "declaration": true,
16 | "declarationMap": false,
17 | "inlineSources": true,
18 | "downlevelIteration": true,
19 | "experimentalDecorators": true,
20 | "esModuleInterop": true,
21 | "allowSyntheticDefaultImports": true,
22 | "moduleResolution": "node",
23 | "importHelpers": true,
24 | "target": "es2017",
25 | "module": "es2020",
26 | "lib": [
27 | "es2020",
28 | "dom"
29 | ]
30 | },
31 | "angularCompilerOptions": {
32 | "compilationMode": "partial",
33 | "enableI18nLegacyMessageIdFormat": false,
34 | "strictInjectionParameters": true,
35 | "strictInputAccessModifiers": true,
36 | "strictTemplates": true
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tsconfig.lint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/spec",
5 | "module": "es2015",
6 | "types": []
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "noEmit": true,
5 | "strictNullChecks": false,
6 | "types": [
7 | "jest",
8 | "node"
9 | ]
10 | },
11 | "include": [
12 | "src/*.spec.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "arrow-return-shorthand": true,
4 | "callable-types": true,
5 | "class-name": true,
6 | "comment-format": [
7 | true,
8 | "check-space"
9 | ],
10 | "curly": true,
11 | "deprecation": {
12 | "severity": "warn"
13 | },
14 | "eofline": true,
15 | "forin": true,
16 | "import-blacklist": [
17 | true,
18 | "rxjs/Rx"
19 | ],
20 | "import-spacing": true,
21 | "indent": [
22 | true,
23 | "spaces"
24 | ],
25 | "interface-over-type-literal": true,
26 | "label-position": true,
27 | "max-line-length": [
28 | true,
29 | 140
30 | ],
31 | "member-access": false,
32 | "member-ordering": [
33 | true,
34 | {
35 | "order": [
36 | "static-field",
37 | "instance-field",
38 | "instance-method",
39 | "static-method"
40 | ]
41 | }
42 | ],
43 | "no-arg": true,
44 | "no-bitwise": true,
45 | "no-console": [
46 | true,
47 | "debug",
48 | "info",
49 | "time",
50 | "timeEnd",
51 | "trace"
52 | ],
53 | "no-construct": true,
54 | "no-debugger": true,
55 | "no-duplicate-super": true,
56 | "no-empty": false,
57 | "no-empty-interface": true,
58 | "no-eval": true,
59 | "no-inferrable-types": [
60 | true,
61 | "ignore-params"
62 | ],
63 | "no-misused-new": true,
64 | "no-non-null-assertion": true,
65 | "no-shadowed-variable": true,
66 | "no-string-literal": false,
67 | "no-string-throw": true,
68 | "no-switch-case-fall-through": true,
69 | "no-trailing-whitespace": true,
70 | "no-unnecessary-initializer": true,
71 | "no-unused-expression": true,
72 | "no-use-before-declare": true,
73 | "no-var-keyword": true,
74 | "object-literal-sort-keys": false,
75 | "one-line": [
76 | true,
77 | "check-open-brace",
78 | "check-catch",
79 | "check-else",
80 | "check-whitespace"
81 | ],
82 | "prefer-const": true,
83 | "quotemark": [
84 | true,
85 | "single"
86 | ],
87 | "radix": true,
88 | "semicolon": [
89 | true,
90 | "always"
91 | ],
92 | "triple-equals": [
93 | true,
94 | "allow-null-check"
95 | ],
96 | "typedef-whitespace": [
97 | true,
98 | {
99 | "call-signature": "nospace",
100 | "index-signature": "nospace",
101 | "parameter": "nospace",
102 | "property-declaration": "nospace",
103 | "variable-declaration": "nospace"
104 | }
105 | ],
106 | "unified-signatures": true,
107 | "variable-name": false,
108 | "whitespace": [
109 | true,
110 | "check-branch",
111 | "check-decl",
112 | "check-operator",
113 | "check-separator",
114 | "check-type"
115 | ]
116 | }
117 | }
118 |
--------------------------------------------------------------------------------