@yext/phonenumber-util 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/pull-request.yml +17 -0
- package/CODEOWNERS +1 -1
- package/README.md +96 -5
- package/package.json +8 -3
- package/src/__tests__/{index.test.js → base.test.js} +1 -1
- package/src/__tests__/geo.test.js +286 -0
- package/src/areaCodeList.js +13 -0
- package/src/compliance.js +31 -0
- package/src/daylightSavings.js +21 -0
- package/src/geo.d.ts +31 -0
- package/src/geo.js +257 -0
- package/src/phoneCodes.js +665 -0
- package/src/timezones.js +148 -0
- /package/src/{index.d.ts → base.d.ts} +0 -0
- /package/src/{index.js → base.js} +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Run pull request checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
name: Test
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-node@v4
|
|
15
|
+
- run: npm ci
|
|
16
|
+
- run: npm run lint
|
|
17
|
+
- run: npm test
|
package/CODEOWNERS
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# The following aliases have approval permissions in this repo:
|
|
2
|
-
* @imbrianj @mi4l
|
|
2
|
+
* @imbrianj @mi4l @DerekWW
|
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Returns a boolean based on whether the passed number is presumed to be valid or
|
|
|
47
47
|
This checks for region code, number length and validity of region code and area code (where applicable).
|
|
48
48
|
|
|
49
49
|
```javascript
|
|
50
|
-
import { isValidPhoneNumber } from 'phonenumber-util';
|
|
50
|
+
import { isValidPhoneNumber } from '@yext/phonenumber-util';
|
|
51
51
|
const validPhoneNumber = '3103496333';
|
|
52
52
|
isValidPhoneNumber(validPhoneNumber); // Returns `true` - "310" is an area code for California
|
|
53
53
|
|
|
@@ -66,11 +66,11 @@ isValidPhoneNumber(invalidIntlNumber); // Returns `false` - "666" is not a valid
|
|
|
66
66
|
Return an object of relevant phone number parts and information.
|
|
67
67
|
|
|
68
68
|
```javascript
|
|
69
|
-
import { getPhoneParts } from 'phonenumber-util';
|
|
69
|
+
import { getPhoneParts } from '@yext/phonenumber-util';
|
|
70
70
|
const validPhoneNumber = '3496333';
|
|
71
71
|
getPhoneParts(validPhoneNumber); // Returns an object, assumed to be US / Canada, region code "1" but no area code can be reliably determined.
|
|
72
72
|
|
|
73
|
-
const validPhoneNumber = '
|
|
73
|
+
const validPhoneNumber = '+923331234567';
|
|
74
74
|
getPhoneParts(validPhoneNumber); // Returns an object, assumed to be Pakistan, region code "92".
|
|
75
75
|
```
|
|
76
76
|
|
|
@@ -109,7 +109,7 @@ Example for US with full area code provided ("310.349.9999"):
|
|
|
109
109
|
```javascript
|
|
110
110
|
{
|
|
111
111
|
areaCode: "310",
|
|
112
|
-
e164: "+
|
|
112
|
+
e164: "+13103499999",
|
|
113
113
|
format: "(xxx) xxx-xxxx",
|
|
114
114
|
formattedNumber: "(310) 349-9999",
|
|
115
115
|
href: "tel:+13103499999",
|
|
@@ -133,7 +133,7 @@ Example for US with full area code provided ("Hey there, my number is 310.349.99
|
|
|
133
133
|
index: 24,
|
|
134
134
|
lastIndex: 36,
|
|
135
135
|
areaCode: '310',
|
|
136
|
-
e164: '+
|
|
136
|
+
e164: '+13103499999',
|
|
137
137
|
format: '(xxx) xxx-xxxx',
|
|
138
138
|
formattedNumber: '(310) 349-9999',
|
|
139
139
|
href: 'tel:+13103499999',
|
|
@@ -151,3 +151,94 @@ Example for US with no area code provided ("Hey there, my number is 349.9999. Pl
|
|
|
151
151
|
```javascript
|
|
152
152
|
[];
|
|
153
153
|
```
|
|
154
|
+
|
|
155
|
+
## Geography / Time Functionality
|
|
156
|
+
|
|
157
|
+
In addition to the above methods, the following methods are also available via a different export.
|
|
158
|
+
|
|
159
|
+
There is additional functionality exposed as `export`, but the primary expected use case is:
|
|
160
|
+
|
|
161
|
+
#### findTimeFromAreaCode
|
|
162
|
+
|
|
163
|
+
Returns an object with geographic and time related information for a given region.
|
|
164
|
+
|
|
165
|
+
_NOTE:_ This is only applicable for United States and Canada.
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
import { findTimeFromAreaCode } from '@yext/phonenumber-util/geo';
|
|
169
|
+
findTimeFromAreaCode('928');
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Example output for Arizona:
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
{
|
|
176
|
+
areaCodeHasMultipleTimezones: false,
|
|
177
|
+
daylightSavings: true,
|
|
178
|
+
estimatedTime: true,
|
|
179
|
+
isQuietHours: false,
|
|
180
|
+
isTCPAQuietHours: false,
|
|
181
|
+
localTime24Hour: "15:00:00",
|
|
182
|
+
localTimeReadable: "3:00:00 PM",
|
|
183
|
+
region: {
|
|
184
|
+
code: "US",
|
|
185
|
+
flag: "🇺🇸",
|
|
186
|
+
name: "United States"
|
|
187
|
+
},
|
|
188
|
+
state: {
|
|
189
|
+
code: "AZ",
|
|
190
|
+
name: "Arizona"
|
|
191
|
+
},
|
|
192
|
+
stateHasMultipleTimezones: false,
|
|
193
|
+
timezoneOffset: "-07:00"
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
import { findTimeFromAreaCode } from '@yext/phonenumber-util/geo';
|
|
199
|
+
findTimeFromAreaCode('250');
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Example output for British Columbia:
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
{
|
|
206
|
+
areaCodeHasMultipleTimezones: true,
|
|
207
|
+
daylightSavings: true,
|
|
208
|
+
estimatedTime: true,
|
|
209
|
+
isCRTCQuietHours: false,
|
|
210
|
+
isQuietHours: false,
|
|
211
|
+
localTime24Hour: "17:00:00",
|
|
212
|
+
localTimeReadable: "5:00:00 PM",
|
|
213
|
+
region: {
|
|
214
|
+
code: "CA",
|
|
215
|
+
flag: "🇨🇦",
|
|
216
|
+
name: "Canada"
|
|
217
|
+
},
|
|
218
|
+
state: {
|
|
219
|
+
code: "BC",
|
|
220
|
+
name: "British Columbia"
|
|
221
|
+
},
|
|
222
|
+
stateHasMultipleTimezones: true,
|
|
223
|
+
timezoneOffset: "-07:00"
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### findRegionFromRegionCode
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
import { findRegionFromRegionCode } from '@yext/phonenumber-util/geo';
|
|
231
|
+
findRegionFromRegionCode('47');
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Returns the string name of a given region name based on region code provided.
|
|
235
|
+
|
|
236
|
+
_NOTE:_ This string is provided in English only (example: "Norway" and not the region-specific name "Norge").
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
{
|
|
240
|
+
code: "NO",
|
|
241
|
+
flag: "🇳🇴",
|
|
242
|
+
name: "Norway"
|
|
243
|
+
}
|
|
244
|
+
```
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yext/phonenumber-util",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"author": "bajohnson@hearsaycorp.com",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
6
|
"description": "Utility for extracting and validating phone numbers",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"main": "src
|
|
8
|
+
"main": "src",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./src/base.js",
|
|
11
|
+
"./geo": "./src/geo.js"
|
|
12
|
+
},
|
|
9
13
|
"types": "src/index.d.ts",
|
|
14
|
+
"sideEffects": false,
|
|
10
15
|
"repository": {
|
|
11
16
|
"type": "git",
|
|
12
17
|
"url": "git+https://github.com/hearsaycorp/phonenumber-util.git"
|
|
@@ -14,7 +19,7 @@
|
|
|
14
19
|
"scripts": {
|
|
15
20
|
"lint": "eslint **/*.js **/__tests__/*.js",
|
|
16
21
|
"format": "prettier --write **/*.js **/__tests__/*.js",
|
|
17
|
-
"test": "vitest",
|
|
22
|
+
"test": "TZ=America/Los_Angeles vitest",
|
|
18
23
|
"build": "node -e \"console.log('No build script for vanilla JS')\"",
|
|
19
24
|
"prepare": "husky"
|
|
20
25
|
},
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isDaylightSavingTime,
|
|
3
|
+
formatTimeOffset,
|
|
4
|
+
offsetTieBreaker,
|
|
5
|
+
findTimeDetails,
|
|
6
|
+
findTimeFromAreaCode,
|
|
7
|
+
findRegionFromRegionCode,
|
|
8
|
+
} from '../geo.js';
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
|
|
11
|
+
const invalidPhone = {
|
|
12
|
+
timezoneOffset: null,
|
|
13
|
+
daylightSavings: null,
|
|
14
|
+
stateHasMultipleTimezones: null,
|
|
15
|
+
areaCodeHasMultipleTimezones: null,
|
|
16
|
+
estimatedTime: false,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const seattlePhone = {
|
|
20
|
+
areaCodeHasMultipleTimezones: false,
|
|
21
|
+
daylightSavings: true,
|
|
22
|
+
estimatedTime: false,
|
|
23
|
+
isQuietHours: false,
|
|
24
|
+
isTCPAQuietHours: false,
|
|
25
|
+
localTime24Hour: '08:00:00',
|
|
26
|
+
localTimeReadable: '8:00:00 AM',
|
|
27
|
+
stateHasMultipleTimezones: false,
|
|
28
|
+
timezoneOffset: '-07:00',
|
|
29
|
+
state: {
|
|
30
|
+
name: 'Washington',
|
|
31
|
+
code: 'WA',
|
|
32
|
+
},
|
|
33
|
+
region: {
|
|
34
|
+
name: 'United States',
|
|
35
|
+
code: 'US',
|
|
36
|
+
flag: '🇺🇸',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const arizonaPhoneJul = {
|
|
41
|
+
areaCodeHasMultipleTimezones: false,
|
|
42
|
+
daylightSavings: true,
|
|
43
|
+
estimatedTime: true,
|
|
44
|
+
isQuietHours: false,
|
|
45
|
+
isTCPAQuietHours: false,
|
|
46
|
+
localTime24Hour: '09:00:00',
|
|
47
|
+
localTimeReadable: '9:00:00 AM',
|
|
48
|
+
stateHasMultipleTimezones: false,
|
|
49
|
+
timezoneOffset: '-06:00',
|
|
50
|
+
state: {
|
|
51
|
+
name: 'Arizona',
|
|
52
|
+
code: 'AZ',
|
|
53
|
+
},
|
|
54
|
+
region: {
|
|
55
|
+
name: 'United States',
|
|
56
|
+
code: 'US',
|
|
57
|
+
flag: '🇺🇸',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const arizonaPhoneDec = {
|
|
62
|
+
areaCodeHasMultipleTimezones: false,
|
|
63
|
+
daylightSavings: false,
|
|
64
|
+
estimatedTime: false,
|
|
65
|
+
isQuietHours: false,
|
|
66
|
+
isTCPAQuietHours: false,
|
|
67
|
+
localTime24Hour: '09:00:00',
|
|
68
|
+
localTimeReadable: '9:00:00 AM',
|
|
69
|
+
stateHasMultipleTimezones: false,
|
|
70
|
+
timezoneOffset: '-07:00',
|
|
71
|
+
state: {
|
|
72
|
+
name: 'Arizona',
|
|
73
|
+
code: 'AZ',
|
|
74
|
+
},
|
|
75
|
+
region: {
|
|
76
|
+
name: 'United States',
|
|
77
|
+
code: 'US',
|
|
78
|
+
flag: '🇺🇸',
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const texasPhone = {
|
|
83
|
+
areaCodeHasMultipleTimezones: true,
|
|
84
|
+
daylightSavings: false,
|
|
85
|
+
estimatedTime: true,
|
|
86
|
+
isQuietHours: false,
|
|
87
|
+
isTCPAQuietHours: false,
|
|
88
|
+
localTime24Hour: '10:00:00',
|
|
89
|
+
localTimeReadable: '10:00:00 AM',
|
|
90
|
+
stateHasMultipleTimezones: true,
|
|
91
|
+
timezoneOffset: '-06:00',
|
|
92
|
+
state: {
|
|
93
|
+
name: 'Texas',
|
|
94
|
+
code: 'TX',
|
|
95
|
+
},
|
|
96
|
+
region: {
|
|
97
|
+
name: 'United States',
|
|
98
|
+
code: 'US',
|
|
99
|
+
flag: '🇺🇸',
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const floridaPhone = {
|
|
104
|
+
areaCodeHasMultipleTimezones: false,
|
|
105
|
+
daylightSavings: false,
|
|
106
|
+
estimatedTime: false,
|
|
107
|
+
isQuietHours: false,
|
|
108
|
+
isTCPAQuietHours: false,
|
|
109
|
+
localTime24Hour: '10:00:00',
|
|
110
|
+
localTimeReadable: '10:00:00 AM',
|
|
111
|
+
stateHasMultipleTimezones: true,
|
|
112
|
+
timezoneOffset: '-06:00',
|
|
113
|
+
state: {
|
|
114
|
+
name: 'Florida',
|
|
115
|
+
code: 'FL',
|
|
116
|
+
},
|
|
117
|
+
region: {
|
|
118
|
+
name: 'United States',
|
|
119
|
+
code: 'US',
|
|
120
|
+
flag: '🇺🇸',
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const hawaiiPhone = {
|
|
125
|
+
areaCodeHasMultipleTimezones: false,
|
|
126
|
+
daylightSavings: false,
|
|
127
|
+
estimatedTime: false,
|
|
128
|
+
isQuietHours: true,
|
|
129
|
+
isTCPAQuietHours: true,
|
|
130
|
+
localTime24Hour: '06:00:00',
|
|
131
|
+
localTimeReadable: '6:00:00 AM',
|
|
132
|
+
stateHasMultipleTimezones: false,
|
|
133
|
+
timezoneOffset: '-10:00',
|
|
134
|
+
state: {
|
|
135
|
+
name: 'Hawaii',
|
|
136
|
+
code: 'HI',
|
|
137
|
+
},
|
|
138
|
+
region: {
|
|
139
|
+
name: 'United States',
|
|
140
|
+
code: 'US',
|
|
141
|
+
flag: '🇺🇸',
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const canadianPhone = {
|
|
146
|
+
areaCodeHasMultipleTimezones: true,
|
|
147
|
+
daylightSavings: true,
|
|
148
|
+
estimatedTime: true,
|
|
149
|
+
isQuietHours: false,
|
|
150
|
+
isCRTCQuietHours: false,
|
|
151
|
+
localTime24Hour: '10:00:00',
|
|
152
|
+
localTimeReadable: '10:00:00 AM',
|
|
153
|
+
stateHasMultipleTimezones: true,
|
|
154
|
+
timezoneOffset: '-05:00',
|
|
155
|
+
state: {
|
|
156
|
+
name: 'British Columbia',
|
|
157
|
+
code: 'BC',
|
|
158
|
+
},
|
|
159
|
+
region: {
|
|
160
|
+
name: 'Canada',
|
|
161
|
+
code: 'CA',
|
|
162
|
+
flag: '🇨🇦',
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
describe('Daylight Savings', () => {
|
|
167
|
+
it('should correctly be determined if the time given is or is not within daylight savings time', () => {
|
|
168
|
+
const daylightSavings = new Date('2024-07-15T12:00:00');
|
|
169
|
+
const notDaylightSavings = new Date('2024-12-15T12:00:00');
|
|
170
|
+
|
|
171
|
+
expect(isDaylightSavingTime(daylightSavings)).toBe(true);
|
|
172
|
+
expect(isDaylightSavingTime(notDaylightSavings)).toBe(false);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe('Formatting time offset', () => {
|
|
177
|
+
it('return a proper ISO 8601 formatted date string, regardless of hour length', () => {
|
|
178
|
+
expect(formatTimeOffset('-8:00')).toBe('-08:00');
|
|
179
|
+
expect(formatTimeOffset('-12:00')).toBe('-12:00');
|
|
180
|
+
expect(formatTimeOffset('+7:00')).toBe('+07:00');
|
|
181
|
+
expect(formatTimeOffset('-3:30')).toBe('-03:30');
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('Errs on the side of caution, minimizing the given time options to the more narrow', () => {
|
|
186
|
+
it('Late at night, the available options for morning should be later', () => {
|
|
187
|
+
expect(
|
|
188
|
+
offsetTieBreaker(['-8:00', '-7:00'], new Date('2024-07-15T23:00:00')),
|
|
189
|
+
).toBe('-7:00');
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('Early in day, the available options for morning should be earlier', () => {
|
|
193
|
+
expect(
|
|
194
|
+
offsetTieBreaker(['-8:00', '-7:00'], new Date('2024-07-15T08:00:00')),
|
|
195
|
+
).toBe('-8:00');
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('Provides compliance quiet hours for any given region', () => {
|
|
200
|
+
it('Returns quiet hours booleans for standard US area', () => {
|
|
201
|
+
// US regions should have TCPA quiet hours but not CRTC quiet hours.
|
|
202
|
+
expect(
|
|
203
|
+
findTimeDetails('-08:00', new Date('2024-07-15T21:00:00'), 'California')
|
|
204
|
+
.isTCPAQuietHours,
|
|
205
|
+
).toEqual(false);
|
|
206
|
+
expect(
|
|
207
|
+
findTimeDetails('-08:00', new Date('2024-07-15T22:00:00'), 'California')
|
|
208
|
+
.isTCPAQuietHours,
|
|
209
|
+
).toEqual(true);
|
|
210
|
+
expect(
|
|
211
|
+
findTimeDetails('-08:00', new Date('2024-07-15T08:00:00'), 'California')
|
|
212
|
+
.isTCPAQuietHours,
|
|
213
|
+
).toEqual(true);
|
|
214
|
+
expect(
|
|
215
|
+
findTimeDetails('-08:00', new Date('2024-07-15T08:00:00'), 'California')
|
|
216
|
+
.isCRTCQuietHours,
|
|
217
|
+
).toEqual(undefined);
|
|
218
|
+
expect(
|
|
219
|
+
findTimeDetails('-08:00', new Date('2024-07-15T09:00:00'), 'California')
|
|
220
|
+
.isTCPAQuietHours,
|
|
221
|
+
).toEqual(false);
|
|
222
|
+
|
|
223
|
+
// Alberta should have CRTC quiet hours but not TCPA quiet hours.
|
|
224
|
+
expect(
|
|
225
|
+
findTimeDetails('-07:00', new Date('2024-07-15T09:00:00'), 'Alberta')
|
|
226
|
+
.isTCPAQuietHours,
|
|
227
|
+
).toEqual(undefined);
|
|
228
|
+
expect(
|
|
229
|
+
findTimeDetails('-07:00', new Date('2024-07-20T07:00:00'), 'Alberta')
|
|
230
|
+
.isCRTCQuietHours,
|
|
231
|
+
).toEqual(true);
|
|
232
|
+
|
|
233
|
+
// Both should have an abstracted general quiet hours value.
|
|
234
|
+
expect(
|
|
235
|
+
findTimeDetails('-08:00', new Date('2024-07-15T08:00:00'), 'California')
|
|
236
|
+
.isQuietHours,
|
|
237
|
+
).toEqual(true);
|
|
238
|
+
expect(
|
|
239
|
+
findTimeDetails('-07:00', new Date('2024-07-15T7:00:00'), 'Alberta')
|
|
240
|
+
.isQuietHours,
|
|
241
|
+
).toEqual(true);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe('Provides general time information for the given phone number (US and Canada only)', () => {
|
|
246
|
+
it('Returns general time information for a phone number region', () => {
|
|
247
|
+
expect(findTimeFromAreaCode(null, new Date('2024-07-15T08:00:00'))).toEqual(
|
|
248
|
+
invalidPhone,
|
|
249
|
+
);
|
|
250
|
+
expect(
|
|
251
|
+
findTimeFromAreaCode('206', new Date('2024-07-15T08:00:00')),
|
|
252
|
+
).toEqual(seattlePhone);
|
|
253
|
+
expect(
|
|
254
|
+
findTimeFromAreaCode('928', new Date('2024-07-15T08:00:00')),
|
|
255
|
+
).toEqual(arizonaPhoneJul);
|
|
256
|
+
expect(
|
|
257
|
+
findTimeFromAreaCode('928', new Date('2024-12-15T08:00:00')),
|
|
258
|
+
).toEqual(arizonaPhoneDec);
|
|
259
|
+
expect(
|
|
260
|
+
findTimeFromAreaCode('432', new Date('2024-12-15T08:00:00')),
|
|
261
|
+
).toEqual(texasPhone);
|
|
262
|
+
expect(
|
|
263
|
+
findTimeFromAreaCode('850', new Date('2024-12-15T08:00:00')),
|
|
264
|
+
).toEqual(floridaPhone);
|
|
265
|
+
expect(
|
|
266
|
+
findTimeFromAreaCode('808', new Date('2024-12-15T08:00:00')),
|
|
267
|
+
).toEqual(hawaiiPhone);
|
|
268
|
+
expect(
|
|
269
|
+
findTimeFromAreaCode('236', new Date('2024-07-20T08:00:00')),
|
|
270
|
+
).toEqual(canadianPhone);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe('Provides region name for a given region code', () => {
|
|
275
|
+
it('Returns region name', () => {
|
|
276
|
+
expect(findRegionFromRegionCode(1).name).toEqual('United States, Canada');
|
|
277
|
+
expect(findRegionFromRegionCode(1, 206).name).toEqual('United States');
|
|
278
|
+
expect(findRegionFromRegionCode(7).name).toEqual('Russia, Kazakhstan');
|
|
279
|
+
expect(findRegionFromRegionCode(20).name).toEqual('Egypt');
|
|
280
|
+
expect(findRegionFromRegionCode(27).name).toEqual('South Africa');
|
|
281
|
+
expect(findRegionFromRegionCode(30).name).toEqual('Greece');
|
|
282
|
+
expect(findRegionFromRegionCode(31).name).toEqual('Netherlands');
|
|
283
|
+
expect(findRegionFromRegionCode(32).name).toEqual('Belgium');
|
|
284
|
+
expect(findRegionFromRegionCode(33).name).toEqual('France');
|
|
285
|
+
});
|
|
286
|
+
});
|
package/src/areaCodeList.js
CHANGED
|
@@ -21,6 +21,7 @@ export const AREA_CODE_LIST = [
|
|
|
21
21
|
'223',
|
|
22
22
|
'224',
|
|
23
23
|
'225',
|
|
24
|
+
'257',
|
|
24
25
|
'228',
|
|
25
26
|
'229',
|
|
26
27
|
'231',
|
|
@@ -89,6 +90,7 @@ export const AREA_CODE_LIST = [
|
|
|
89
90
|
'350',
|
|
90
91
|
'351',
|
|
91
92
|
'352',
|
|
93
|
+
'357',
|
|
92
94
|
'360',
|
|
93
95
|
'361',
|
|
94
96
|
'363',
|
|
@@ -134,17 +136,20 @@ export const AREA_CODE_LIST = [
|
|
|
134
136
|
'447',
|
|
135
137
|
'448',
|
|
136
138
|
'450',
|
|
139
|
+
'457',
|
|
137
140
|
'458',
|
|
138
141
|
'463',
|
|
139
142
|
'464',
|
|
140
143
|
'469',
|
|
141
144
|
'470',
|
|
145
|
+
'471',
|
|
142
146
|
'472',
|
|
143
147
|
'473',
|
|
144
148
|
'475',
|
|
145
149
|
'478',
|
|
146
150
|
'479',
|
|
147
151
|
'480',
|
|
152
|
+
'483',
|
|
148
153
|
'484',
|
|
149
154
|
'501',
|
|
150
155
|
'502',
|
|
@@ -212,6 +217,7 @@ export const AREA_CODE_LIST = [
|
|
|
212
217
|
'618',
|
|
213
218
|
'619',
|
|
214
219
|
'620',
|
|
220
|
+
'621',
|
|
215
221
|
'623',
|
|
216
222
|
'626',
|
|
217
223
|
'628',
|
|
@@ -241,6 +247,7 @@ export const AREA_CODE_LIST = [
|
|
|
241
247
|
'671',
|
|
242
248
|
'672',
|
|
243
249
|
'678',
|
|
250
|
+
'679',
|
|
244
251
|
'680',
|
|
245
252
|
'681',
|
|
246
253
|
'682',
|
|
@@ -269,14 +276,18 @@ export const AREA_CODE_LIST = [
|
|
|
269
276
|
'725',
|
|
270
277
|
'726',
|
|
271
278
|
'727',
|
|
279
|
+
'728',
|
|
280
|
+
'729',
|
|
272
281
|
'731',
|
|
273
282
|
'732',
|
|
274
283
|
'734',
|
|
275
284
|
'737',
|
|
285
|
+
'738',
|
|
276
286
|
'740',
|
|
277
287
|
'742',
|
|
278
288
|
'743',
|
|
279
289
|
'747',
|
|
290
|
+
'748',
|
|
280
291
|
'754',
|
|
281
292
|
'757',
|
|
282
293
|
'758',
|
|
@@ -330,6 +341,7 @@ export const AREA_CODE_LIST = [
|
|
|
330
341
|
'832',
|
|
331
342
|
'833',
|
|
332
343
|
'835',
|
|
344
|
+
'837',
|
|
333
345
|
'838',
|
|
334
346
|
'839',
|
|
335
347
|
'840',
|
|
@@ -392,6 +404,7 @@ export const AREA_CODE_LIST = [
|
|
|
392
404
|
'939',
|
|
393
405
|
'940',
|
|
394
406
|
'941',
|
|
407
|
+
'942',
|
|
395
408
|
'943',
|
|
396
409
|
'945',
|
|
397
410
|
'947',
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const TCPA_QUIET_HOURS = {
|
|
2
|
+
start: 8,
|
|
3
|
+
end: 21,
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export const CRTC_QUIET_HOURS = {
|
|
7
|
+
weekdays: {
|
|
8
|
+
start: 9,
|
|
9
|
+
end: 21.5,
|
|
10
|
+
},
|
|
11
|
+
weekends: {
|
|
12
|
+
start: 10,
|
|
13
|
+
end: 18,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const CRTC_STATES = [
|
|
18
|
+
'Alberta',
|
|
19
|
+
'British Columbia',
|
|
20
|
+
'Manitoba',
|
|
21
|
+
'New Brunswick',
|
|
22
|
+
'Newfoundland and Labrador',
|
|
23
|
+
'Northwest Territories',
|
|
24
|
+
'Nova Scotia',
|
|
25
|
+
'Nunavut',
|
|
26
|
+
'Ontario',
|
|
27
|
+
'Nova Scotia and Prince Edward Island',
|
|
28
|
+
'Quebec',
|
|
29
|
+
'Saskatchewan',
|
|
30
|
+
'Yukon',
|
|
31
|
+
];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const STATES_THAT_DONT_HAVE_DAYLIGHT_SAVINGS = [
|
|
2
|
+
'Arizona',
|
|
3
|
+
'Hawaii',
|
|
4
|
+
'British Columbia',
|
|
5
|
+
'Puerto Rico',
|
|
6
|
+
'Saskatchewan',
|
|
7
|
+
'Virgin Islands',
|
|
8
|
+
'Yukon, Northwest Territories, and Nunavut',
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
// Arizona does not follow Daylight Savings, but the Navajo Nation does. The
|
|
12
|
+
// 928 area code spans both Arizone (no DST) and Navajo Nation lands (DST).
|
|
13
|
+
export const AREA_CODES_WITH_MULTIPLE_DAYLIGHT_SAVINGS = {
|
|
14
|
+
928: 'Arizona',
|
|
15
|
+
236: 'British Columbia',
|
|
16
|
+
250: 'British Columbia',
|
|
17
|
+
257: 'British Columbia',
|
|
18
|
+
672: 'British Columbia',
|
|
19
|
+
778: 'British Columbia',
|
|
20
|
+
306: 'Saskatchewan',
|
|
21
|
+
};
|
package/src/geo.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function isDaylightSavingTime(date?: Date): boolean;
|
|
2
|
+
|
|
3
|
+
export function formatTimeOffset(offset: string): string;
|
|
4
|
+
|
|
5
|
+
export function offsetTieBreaker(timezones: string[], date: Date): string;
|
|
6
|
+
|
|
7
|
+
export function findTimeDetails(
|
|
8
|
+
offset: string,
|
|
9
|
+
date: Date,
|
|
10
|
+
state: string
|
|
11
|
+
): {
|
|
12
|
+
localTimeReadable: string;
|
|
13
|
+
localTime24Hour: string;
|
|
14
|
+
isTCPAQuietHours?: boolean;
|
|
15
|
+
isCRTCQuietHours?: boolean;
|
|
16
|
+
isQuietHours: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function findTimeFromAreaCode(
|
|
20
|
+
areaCode: string,
|
|
21
|
+
date?: Date
|
|
22
|
+
): {
|
|
23
|
+
timezoneOffset: string | null;
|
|
24
|
+
daylightSavings: boolean | null;
|
|
25
|
+
stateHasMultipleTimezones: boolean | null;
|
|
26
|
+
state: string | null;
|
|
27
|
+
areaCodeHasMultipleTimezones: boolean | null;
|
|
28
|
+
estimatedTime: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function findRegionFromRegionCode(regionCode: string): string | undefined;
|