geo-coordinates-parser 1.7.1 → 1.7.3
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/README.md +2 -0
- package/dist/cjs/converter.js +27 -7
- package/dist/cjs/regex.d.ts +1 -0
- package/dist/cjs/regex.js +9 -6
- package/dist/cjs/tests/failFormats.js +4 -1
- package/dist/cjs/tests/testIndividual.js +12 -13
- package/dist/cjs/tests/testformats.js +7 -0
- package/dist/cjs/toCoordinateFormat.js +9 -5
- package/dist/mjs/converter.js +28 -8
- package/dist/mjs/regex.d.ts +1 -0
- package/dist/mjs/regex.js +8 -6
- package/dist/mjs/tests/failFormats.js +4 -1
- package/dist/mjs/tests/testIndividual.js +12 -13
- package/dist/mjs/tests/testformats.js +7 -0
- package/dist/mjs/toCoordinateFormat.js +9 -5
- package/package.json +1 -1
package/README.md
CHANGED
@@ -46,6 +46,8 @@ converted.decimalLatitude; // 40.446195 ✓
|
|
46
46
|
converted.decimalLongitude; // -79.948862 ✓
|
47
47
|
converted.verbatimLatitude; // '40° 26.7717' ✓
|
48
48
|
converted.verbatimLongitude; // '-79° 56.93172' ✓
|
49
|
+
converted.decimalCoordinates; // for convenience
|
50
|
+
convert.originalFormat; // 'DM' to indicate degrees and minutes
|
49
51
|
```
|
50
52
|
The returned object includes properties verbatimCoordinates, verbatimLatitude, verbatimLongitude, decimalLatitude, decimalLatitude, and decimalCoordinates.
|
51
53
|
|
package/dist/cjs/converter.js
CHANGED
@@ -23,8 +23,12 @@ function converter(coordsString, decimalPlaces) {
|
|
23
23
|
let ddLng = null;
|
24
24
|
let latdir = "";
|
25
25
|
let lngdir = "";
|
26
|
+
let originalFormat = null;
|
26
27
|
let match = [];
|
27
28
|
let matchSuccess = false;
|
29
|
+
if (regex_js_1.dm_invalid.test(coordsString)) {
|
30
|
+
throw new Error("invalid coordinate value");
|
31
|
+
}
|
28
32
|
if (regex_js_1.dm_numbers.test(coordsString)) {
|
29
33
|
match = regex_js_1.dm_numbers.exec(coordsString);
|
30
34
|
matchSuccess = checkMatch(match);
|
@@ -37,6 +41,7 @@ function converter(coordsString, decimalPlaces) {
|
|
37
41
|
if (Number(match[3]) < 0) {
|
38
42
|
ddLng *= -1;
|
39
43
|
}
|
44
|
+
originalFormat = "DM";
|
40
45
|
}
|
41
46
|
else {
|
42
47
|
throw new Error("invalid coordinate format");
|
@@ -55,6 +60,7 @@ function converter(coordsString, decimalPlaces) {
|
|
55
60
|
if (ddLng.includes(',')) {
|
56
61
|
ddLng = ddLng.replace(',', '.');
|
57
62
|
}
|
63
|
+
originalFormat = "DD";
|
58
64
|
//validation, we don't want things like 23.00000
|
59
65
|
//some more validation: no zero coords or degrees only
|
60
66
|
if (Number(Math.round(ddLat)) == Number(ddLat)) {
|
@@ -84,9 +90,11 @@ function converter(coordsString, decimalPlaces) {
|
|
84
90
|
ddLat = Math.abs(parseInt(match[2]));
|
85
91
|
if (match[4]) {
|
86
92
|
ddLat += match[4] / 60;
|
93
|
+
originalFormat = "DM";
|
87
94
|
}
|
88
95
|
if (match[6]) {
|
89
96
|
ddLat += match[6].replace(',', '.') / 3600;
|
97
|
+
originalFormat = "DMS";
|
90
98
|
}
|
91
99
|
if (parseInt(match[2]) < 0) {
|
92
100
|
ddLat = -1 * ddLat;
|
@@ -122,9 +130,11 @@ function converter(coordsString, decimalPlaces) {
|
|
122
130
|
ddLat = Math.abs(parseInt(match[2]));
|
123
131
|
if (match[4]) {
|
124
132
|
ddLat += match[4] / 60;
|
133
|
+
originalFormat = "DM";
|
125
134
|
}
|
126
135
|
if (match[6]) {
|
127
136
|
ddLat += match[6] / 3600;
|
137
|
+
originalFormat = "DMS";
|
128
138
|
}
|
129
139
|
if (parseInt(match[2]) < 0) {
|
130
140
|
ddLat = -1 * ddLat;
|
@@ -156,13 +166,19 @@ function converter(coordsString, decimalPlaces) {
|
|
156
166
|
else if (regex_js_1.coords_other.test(coordsString)) {
|
157
167
|
match = regex_js_1.coords_other.exec(coordsString);
|
158
168
|
matchSuccess = checkMatch(match);
|
169
|
+
// we need an extra check here for things that matched that shouldn't have
|
170
|
+
if (match.filter(x => x).length <= 5) {
|
171
|
+
throw new Error("invalid coordinates format");
|
172
|
+
}
|
159
173
|
if (matchSuccess) {
|
160
174
|
ddLat = Math.abs(parseInt(match[2]));
|
161
175
|
if (match[4]) {
|
162
176
|
ddLat += match[4].replace(',', '.') / 60;
|
177
|
+
originalFormat = "DM";
|
163
178
|
}
|
164
179
|
if (match[6]) {
|
165
180
|
ddLat += match[6].replace(',', '.') / 3600;
|
181
|
+
originalFormat = "DMS";
|
166
182
|
}
|
167
183
|
if (parseInt(match[2]) < 0) {
|
168
184
|
ddLat = -1 * ddLat;
|
@@ -209,6 +225,13 @@ function converter(coordsString, decimalPlaces) {
|
|
209
225
|
if (latdir && latdir == lngdir) {
|
210
226
|
throw new Error("invalid coordinates format");
|
211
227
|
}
|
228
|
+
// a bit of tidying up...
|
229
|
+
if (ddLat.toString().includes(',')) {
|
230
|
+
ddLat = ddLat.replace(',', '.');
|
231
|
+
}
|
232
|
+
if (ddLng.toString().includes(',')) {
|
233
|
+
ddLng = ddLng.replace(',', '.');
|
234
|
+
}
|
212
235
|
//make sure the signs and cardinal directions match
|
213
236
|
let patt = /S|SOUTH/i;
|
214
237
|
if (patt.test(latdir)) {
|
@@ -284,13 +307,6 @@ function converter(coordsString, decimalPlaces) {
|
|
284
307
|
if (/^\d+$/.test(verbatimLat) || /^\d+$/.test(verbatimLng)) {
|
285
308
|
throw new Error('degree only coordinate/s provided');
|
286
309
|
}
|
287
|
-
// last bit of tidying up...
|
288
|
-
if (isNaN(ddLat) && ddLat.includes(',')) {
|
289
|
-
ddLat = ddLat.replace(',', '.');
|
290
|
-
}
|
291
|
-
if (isNaN(ddLng) && ddLng.includes(',')) {
|
292
|
-
ddLng = ddLng.replace(',', '.');
|
293
|
-
}
|
294
310
|
//all done!!
|
295
311
|
//just truncate the decimals appropriately
|
296
312
|
ddLat = Number(Number(ddLat).toFixed(decimalPlaces));
|
@@ -302,6 +318,7 @@ function converter(coordsString, decimalPlaces) {
|
|
302
318
|
decimalLatitude: ddLat,
|
303
319
|
decimalLongitude: ddLng,
|
304
320
|
decimalCoordinates: `${ddLat},${ddLng}`,
|
321
|
+
originalFormat,
|
305
322
|
closeEnough: coordsCloseEnough,
|
306
323
|
toCoordinateFormat: toCoordinateFormat_js_1.default
|
307
324
|
});
|
@@ -360,6 +377,9 @@ function decimalsCloseEnough(dec1, dec2) {
|
|
360
377
|
}
|
361
378
|
}
|
362
379
|
function coordsCloseEnough(coordsToTest) {
|
380
|
+
if (!coordsToTest) {
|
381
|
+
throw new Error('coords must be provided');
|
382
|
+
}
|
363
383
|
if (coordsToTest.includes(',')) {
|
364
384
|
const coords = coordsToTest.split(',');
|
365
385
|
if (Number(coords[0]) == NaN || Number(coords[1]) == NaN) {
|
package/dist/cjs/regex.d.ts
CHANGED
package/dist/cjs/regex.js
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
"use strict";
|
2
2
|
//Coordinates pattern matching regex
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
4
|
-
exports.coords_other = exports.dms_abbr = exports.dms_periods = exports.dd_re = exports.dm_numbers = void 0;
|
4
|
+
exports.coords_other = exports.dms_abbr = exports.dms_periods = exports.dd_re = exports.dm_numbers = exports.dm_invalid = void 0;
|
5
|
+
//DM with invalid minutes (goes to coords_other); this is just a shortened version of that to create a guard condition
|
6
|
+
const dm_invalid = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([6-9][0-9])\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([6-9][0-9])\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*(EAST|WEST|[EW])?$/i;
|
7
|
+
exports.dm_invalid = dm_invalid;
|
5
8
|
//DM as numbers only - see issue #15
|
6
|
-
const dm_numbers =
|
9
|
+
const dm_numbers = /^([+-]?[0-8]?[0-9])\s+([0-5]?[0-9]\.\d{3,})[\s,]{1,}([+-]?[0-1]?[0-9]?[0-9])\s+([0-5]?[0-9]\.\d{3,})$/;
|
7
10
|
exports.dm_numbers = dm_numbers;
|
8
11
|
//decimal degrees
|
9
|
-
const dd_re =
|
12
|
+
const dd_re = /^(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))[\s]*([•º°]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/;]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))[\s]*([•º°]?)[\s]*(EAST|WEST|[EW])?$/i;
|
10
13
|
exports.dd_re = dd_re;
|
11
14
|
//degrees minutes seconds with '.' as separator - gives array with 15 values
|
12
|
-
const dms_periods =
|
15
|
+
const dms_periods = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*(\.)\s*([0-5]?[0-9])\s*(\.)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*(\.)\s*([0-5]?[0-9])\s*(\.)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(EAST|WEST|[EW])?$/i;
|
13
16
|
exports.dms_periods = dms_periods;
|
14
17
|
//degrees minutes seconds with words 'degrees, minutes, seconds' as separators (needed because the s of seconds messes with the S of SOUTH) - gives array of 17 values
|
15
|
-
const dms_abbr =
|
18
|
+
const dms_abbr = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*(D(?:EG)?(?:REES)?)\s*([0-5]?[0-9])\s*(M(?:IN)?(?:UTES)?)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(S(?:EC)?(?:ONDS)?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*(D(?:EG)?(?:REES)?)\s*([0-5]?[0-9])\s*(M(?:IN)?(?:UTES)?)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(S(?:EC)?(?:ONDS)?)\s*(EAST|WEST|[EW])?$/i;
|
16
19
|
exports.dms_abbr = dms_abbr;
|
17
20
|
//everything else - gives array of 17 values
|
18
|
-
const coords_other =
|
21
|
+
const coords_other = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([0-5]?[0-9](?:[\.,]\d{1,})?)?\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*,?((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(''|′′|’’|´´|["″”\.])?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([0-5]?[0-9](?:[\.,]\d{1,})?)?\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*,?((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(''|′′|´´|’’|["″”\.])?\s*(EAST|WEST|[EW])?$/i;
|
19
22
|
exports.coords_other = coords_other;
|
@@ -21,6 +21,9 @@ const failingFormats = [
|
|
21
21
|
'S 90°4\'17.698" S 23°4\'17.698"',
|
22
22
|
'27.45.34 S S 23.23.23',
|
23
23
|
'27.45.34 23.23.23 E',
|
24
|
-
'8°83S 35°67E '
|
24
|
+
'8°83S 35°67E ',
|
25
|
+
'25.62S, 27.77E',
|
26
|
+
'-254.4602, 31.53681',
|
27
|
+
'1234.524234234, 1241.1541241234',
|
25
28
|
];
|
26
29
|
exports.default = failingFormats;
|
@@ -9,21 +9,20 @@ const converter_js_1 = __importDefault(require("../converter.js"));
|
|
9
9
|
//const test = `45°5'46.8134"N, 18°30'36.7124"E`
|
10
10
|
//const test = `50 8.2914,-5 2.4447`
|
11
11
|
//const test = `8°83S 35°67E`
|
12
|
-
const test = `N 48° 30,6410', E 18° 57,4583'
|
12
|
+
//const test = `N 48° 30,6410', E 18° 57,4583'`
|
13
|
+
//const test = '-254.4602, 31.53681'
|
14
|
+
const test = '25.62S, 27.77E';
|
15
|
+
//const correctDecimals = '-25.533333, 27.283333'
|
16
|
+
let converted;
|
13
17
|
try {
|
14
|
-
|
15
|
-
console.log(converted);
|
16
|
-
console.log(converted.toCoordinateFormat(converter_js_1.default.to.DM));
|
17
|
-
//and just to make sure it's frozen
|
18
|
-
let previous = converted.decimalLatitude;
|
19
|
-
converted.decimalLatitude = 24;
|
20
|
-
if (converted.decimalLatitude === previous) {
|
21
|
-
console.log('the result is frozen');
|
22
|
-
}
|
23
|
-
else {
|
24
|
-
console.error('!!!The result is not frozen!!!!');
|
25
|
-
}
|
18
|
+
converted = (0, converter_js_1.default)(test);
|
26
19
|
}
|
27
20
|
catch (err) {
|
28
21
|
console.log(err.message);
|
22
|
+
process.exit();
|
23
|
+
}
|
24
|
+
console.log(converted);
|
25
|
+
console.log('DM:', converted.toCoordinateFormat(converter_js_1.default.to.DM).replace(/\s/g, '')); // shortened format
|
26
|
+
if (!converted.closeEnough(correctDecimals)) {
|
27
|
+
console.error('!!! conversion is incorrect !!!');
|
29
28
|
}
|
@@ -363,6 +363,13 @@ const otherFormats = [
|
|
363
363
|
verbatimLongitude: `E 18° 57,4583'`,
|
364
364
|
decimalLatitude: 48.51068,
|
365
365
|
decimalLongitude: 18.95764
|
366
|
+
},
|
367
|
+
{
|
368
|
+
verbatimCoordinates: `1.23456, 18.33453`,
|
369
|
+
verbatimLatitude: `1.23456`,
|
370
|
+
verbatimLongitude: `18.33453`,
|
371
|
+
decimalLatitude: 1.23456,
|
372
|
+
decimalLongitude: 18.33453
|
366
373
|
}
|
367
374
|
];
|
368
375
|
function getAllTestFormats() {
|
@@ -28,8 +28,12 @@ function toCoordinateFormat(format) {
|
|
28
28
|
const minutesLatitudeNotTruncated = (absoluteLatitude - degreesLatitude) * 60;
|
29
29
|
const minutesLongitudeNotTruncated = (absoluteLongitude - degreesLongitude) * 60;
|
30
30
|
if (format == 'DM') {
|
31
|
-
|
32
|
-
|
31
|
+
let dmMinsLatitude = round(minutesLatitudeNotTruncated, 3).toFixed(3).padStart(6, '0');
|
32
|
+
let dmMinsLongitude = round(minutesLongitudeNotTruncated, 3).toFixed(3).padStart(6, '0');
|
33
|
+
if (dmMinsLatitude.endsWith('.000') && dmMinsLongitude.endsWith('.000')) {
|
34
|
+
dmMinsLatitude = dmMinsLatitude.replace(/\.000$/, '');
|
35
|
+
dmMinsLongitude = dmMinsLongitude.replace(/\.000$/, '');
|
36
|
+
}
|
33
37
|
result = `${degreesLatitude}° ${dmMinsLatitude}' ${latDir}, ${degreesLongitude}° ${dmMinsLongitude}' ${longDir}`;
|
34
38
|
}
|
35
39
|
if (format == "DMS") {
|
@@ -40,9 +44,9 @@ function toCoordinateFormat(format) {
|
|
40
44
|
const latMinutesString = latMinutes.toString().padStart(2, '0');
|
41
45
|
const longMinutesString = longMinutes.toString().padStart(2, '0');
|
42
46
|
// if they both end in .0 we drop the .0
|
43
|
-
if (latSeconds.endsWith('.0
|
44
|
-
latSeconds = latSeconds.replace(/\.0
|
45
|
-
longSeconds = longSeconds.replace(/\.0
|
47
|
+
if (latSeconds.endsWith('.0') && longSeconds.endsWith('.0')) {
|
48
|
+
latSeconds = latSeconds.replace(/\.0$/, '');
|
49
|
+
longSeconds = longSeconds.replace(/\.0$/, '');
|
46
50
|
}
|
47
51
|
result = `${degreesLatitude}° ${latMinutesString}' ${latSeconds}" ${latDir}, ${degreesLongitude}° ${longMinutesString}' ${longSeconds}" ${longDir}`;
|
48
52
|
}
|
package/dist/mjs/converter.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
//function for converting coordinates from a string to decimal and verbatim
|
2
2
|
//this is just a comment
|
3
|
-
import { dm_numbers, dd_re, dms_periods, dms_abbr, coords_other } from './regex.js';
|
3
|
+
import { dm_invalid, dm_numbers, dd_re, dms_periods, dms_abbr, coords_other } from './regex.js';
|
4
4
|
import toCoordinateFormat from './toCoordinateFormat.js';
|
5
5
|
/**
|
6
6
|
* Function for converting coordinates in a variety of formats to decimal coordinates
|
@@ -18,8 +18,12 @@ function converter(coordsString, decimalPlaces) {
|
|
18
18
|
let ddLng = null;
|
19
19
|
let latdir = "";
|
20
20
|
let lngdir = "";
|
21
|
+
let originalFormat = null;
|
21
22
|
let match = [];
|
22
23
|
let matchSuccess = false;
|
24
|
+
if (dm_invalid.test(coordsString)) {
|
25
|
+
throw new Error("invalid coordinate value");
|
26
|
+
}
|
23
27
|
if (dm_numbers.test(coordsString)) {
|
24
28
|
match = dm_numbers.exec(coordsString);
|
25
29
|
matchSuccess = checkMatch(match);
|
@@ -32,6 +36,7 @@ function converter(coordsString, decimalPlaces) {
|
|
32
36
|
if (Number(match[3]) < 0) {
|
33
37
|
ddLng *= -1;
|
34
38
|
}
|
39
|
+
originalFormat = "DM";
|
35
40
|
}
|
36
41
|
else {
|
37
42
|
throw new Error("invalid coordinate format");
|
@@ -50,6 +55,7 @@ function converter(coordsString, decimalPlaces) {
|
|
50
55
|
if (ddLng.includes(',')) {
|
51
56
|
ddLng = ddLng.replace(',', '.');
|
52
57
|
}
|
58
|
+
originalFormat = "DD";
|
53
59
|
//validation, we don't want things like 23.00000
|
54
60
|
//some more validation: no zero coords or degrees only
|
55
61
|
if (Number(Math.round(ddLat)) == Number(ddLat)) {
|
@@ -79,9 +85,11 @@ function converter(coordsString, decimalPlaces) {
|
|
79
85
|
ddLat = Math.abs(parseInt(match[2]));
|
80
86
|
if (match[4]) {
|
81
87
|
ddLat += match[4] / 60;
|
88
|
+
originalFormat = "DM";
|
82
89
|
}
|
83
90
|
if (match[6]) {
|
84
91
|
ddLat += match[6].replace(',', '.') / 3600;
|
92
|
+
originalFormat = "DMS";
|
85
93
|
}
|
86
94
|
if (parseInt(match[2]) < 0) {
|
87
95
|
ddLat = -1 * ddLat;
|
@@ -117,9 +125,11 @@ function converter(coordsString, decimalPlaces) {
|
|
117
125
|
ddLat = Math.abs(parseInt(match[2]));
|
118
126
|
if (match[4]) {
|
119
127
|
ddLat += match[4] / 60;
|
128
|
+
originalFormat = "DM";
|
120
129
|
}
|
121
130
|
if (match[6]) {
|
122
131
|
ddLat += match[6] / 3600;
|
132
|
+
originalFormat = "DMS";
|
123
133
|
}
|
124
134
|
if (parseInt(match[2]) < 0) {
|
125
135
|
ddLat = -1 * ddLat;
|
@@ -151,13 +161,19 @@ function converter(coordsString, decimalPlaces) {
|
|
151
161
|
else if (coords_other.test(coordsString)) {
|
152
162
|
match = coords_other.exec(coordsString);
|
153
163
|
matchSuccess = checkMatch(match);
|
164
|
+
// we need an extra check here for things that matched that shouldn't have
|
165
|
+
if (match.filter(x => x).length <= 5) {
|
166
|
+
throw new Error("invalid coordinates format");
|
167
|
+
}
|
154
168
|
if (matchSuccess) {
|
155
169
|
ddLat = Math.abs(parseInt(match[2]));
|
156
170
|
if (match[4]) {
|
157
171
|
ddLat += match[4].replace(',', '.') / 60;
|
172
|
+
originalFormat = "DM";
|
158
173
|
}
|
159
174
|
if (match[6]) {
|
160
175
|
ddLat += match[6].replace(',', '.') / 3600;
|
176
|
+
originalFormat = "DMS";
|
161
177
|
}
|
162
178
|
if (parseInt(match[2]) < 0) {
|
163
179
|
ddLat = -1 * ddLat;
|
@@ -204,6 +220,13 @@ function converter(coordsString, decimalPlaces) {
|
|
204
220
|
if (latdir && latdir == lngdir) {
|
205
221
|
throw new Error("invalid coordinates format");
|
206
222
|
}
|
223
|
+
// a bit of tidying up...
|
224
|
+
if (ddLat.toString().includes(',')) {
|
225
|
+
ddLat = ddLat.replace(',', '.');
|
226
|
+
}
|
227
|
+
if (ddLng.toString().includes(',')) {
|
228
|
+
ddLng = ddLng.replace(',', '.');
|
229
|
+
}
|
207
230
|
//make sure the signs and cardinal directions match
|
208
231
|
let patt = /S|SOUTH/i;
|
209
232
|
if (patt.test(latdir)) {
|
@@ -279,13 +302,6 @@ function converter(coordsString, decimalPlaces) {
|
|
279
302
|
if (/^\d+$/.test(verbatimLat) || /^\d+$/.test(verbatimLng)) {
|
280
303
|
throw new Error('degree only coordinate/s provided');
|
281
304
|
}
|
282
|
-
// last bit of tidying up...
|
283
|
-
if (isNaN(ddLat) && ddLat.includes(',')) {
|
284
|
-
ddLat = ddLat.replace(',', '.');
|
285
|
-
}
|
286
|
-
if (isNaN(ddLng) && ddLng.includes(',')) {
|
287
|
-
ddLng = ddLng.replace(',', '.');
|
288
|
-
}
|
289
305
|
//all done!!
|
290
306
|
//just truncate the decimals appropriately
|
291
307
|
ddLat = Number(Number(ddLat).toFixed(decimalPlaces));
|
@@ -297,6 +313,7 @@ function converter(coordsString, decimalPlaces) {
|
|
297
313
|
decimalLatitude: ddLat,
|
298
314
|
decimalLongitude: ddLng,
|
299
315
|
decimalCoordinates: `${ddLat},${ddLng}`,
|
316
|
+
originalFormat,
|
300
317
|
closeEnough: coordsCloseEnough,
|
301
318
|
toCoordinateFormat
|
302
319
|
});
|
@@ -355,6 +372,9 @@ function decimalsCloseEnough(dec1, dec2) {
|
|
355
372
|
}
|
356
373
|
}
|
357
374
|
function coordsCloseEnough(coordsToTest) {
|
375
|
+
if (!coordsToTest) {
|
376
|
+
throw new Error('coords must be provided');
|
377
|
+
}
|
358
378
|
if (coordsToTest.includes(',')) {
|
359
379
|
const coords = coordsToTest.split(',');
|
360
380
|
if (Number(coords[0]) == NaN || Number(coords[1]) == NaN) {
|
package/dist/mjs/regex.d.ts
CHANGED
package/dist/mjs/regex.js
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
//Coordinates pattern matching regex
|
2
|
+
//DM with invalid minutes (goes to coords_other); this is just a shortened version of that to create a guard condition
|
3
|
+
const dm_invalid = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([6-9][0-9])\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([6-9][0-9])\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*(EAST|WEST|[EW])?$/i;
|
2
4
|
//DM as numbers only - see issue #15
|
3
|
-
const dm_numbers =
|
5
|
+
const dm_numbers = /^([+-]?[0-8]?[0-9])\s+([0-5]?[0-9]\.\d{3,})[\s,]{1,}([+-]?[0-1]?[0-9]?[0-9])\s+([0-5]?[0-9]\.\d{3,})$/;
|
4
6
|
//decimal degrees
|
5
|
-
const dd_re =
|
7
|
+
const dd_re = /^(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))[\s]*([•º°]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/;]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))[\s]*([•º°]?)[\s]*(EAST|WEST|[EW])?$/i;
|
6
8
|
//degrees minutes seconds with '.' as separator - gives array with 15 values
|
7
|
-
const dms_periods =
|
9
|
+
const dms_periods = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*(\.)\s*([0-5]?[0-9])\s*(\.)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*(\.)\s*([0-5]?[0-9])\s*(\.)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(EAST|WEST|[EW])?$/i;
|
8
10
|
//degrees minutes seconds with words 'degrees, minutes, seconds' as separators (needed because the s of seconds messes with the S of SOUTH) - gives array of 17 values
|
9
|
-
const dms_abbr =
|
11
|
+
const dms_abbr = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*(D(?:EG)?(?:REES)?)\s*([0-5]?[0-9])\s*(M(?:IN)?(?:UTES)?)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(S(?:EC)?(?:ONDS)?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*(D(?:EG)?(?:REES)?)\s*([0-5]?[0-9])\s*(M(?:IN)?(?:UTES)?)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(S(?:EC)?(?:ONDS)?)\s*(EAST|WEST|[EW])?$/i;
|
10
12
|
//everything else - gives array of 17 values
|
11
|
-
const coords_other =
|
12
|
-
export { dm_numbers, dd_re, dms_periods, dms_abbr, coords_other };
|
13
|
+
const coords_other = /^(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([0-5]?[0-9](?:[\.,]\d{1,})?)?\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*,?((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(''|′′|’’|´´|["″”\.])?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([0-5]?[0-9](?:[\.,]\d{1,})?)?\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*,?((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(''|′′|´´|’’|["″”\.])?\s*(EAST|WEST|[EW])?$/i;
|
14
|
+
export { dm_invalid, dm_numbers, dd_re, dms_periods, dms_abbr, coords_other };
|
@@ -19,6 +19,9 @@ const failingFormats = [
|
|
19
19
|
'S 90°4\'17.698" S 23°4\'17.698"',
|
20
20
|
'27.45.34 S S 23.23.23',
|
21
21
|
'27.45.34 23.23.23 E',
|
22
|
-
'8°83S 35°67E '
|
22
|
+
'8°83S 35°67E ',
|
23
|
+
'25.62S, 27.77E',
|
24
|
+
'-254.4602, 31.53681',
|
25
|
+
'1234.524234234, 1241.1541241234',
|
23
26
|
];
|
24
27
|
export default failingFormats;
|
@@ -4,21 +4,20 @@ import convert from '../converter.js';
|
|
4
4
|
//const test = `45°5'46.8134"N, 18°30'36.7124"E`
|
5
5
|
//const test = `50 8.2914,-5 2.4447`
|
6
6
|
//const test = `8°83S 35°67E`
|
7
|
-
const test = `N 48° 30,6410', E 18° 57,4583'
|
7
|
+
//const test = `N 48° 30,6410', E 18° 57,4583'`
|
8
|
+
//const test = '-254.4602, 31.53681'
|
9
|
+
const test = '25.62S, 27.77E';
|
10
|
+
//const correctDecimals = '-25.533333, 27.283333'
|
11
|
+
let converted;
|
8
12
|
try {
|
9
|
-
|
10
|
-
console.log(converted);
|
11
|
-
console.log(converted.toCoordinateFormat(convert.to.DM));
|
12
|
-
//and just to make sure it's frozen
|
13
|
-
let previous = converted.decimalLatitude;
|
14
|
-
converted.decimalLatitude = 24;
|
15
|
-
if (converted.decimalLatitude === previous) {
|
16
|
-
console.log('the result is frozen');
|
17
|
-
}
|
18
|
-
else {
|
19
|
-
console.error('!!!The result is not frozen!!!!');
|
20
|
-
}
|
13
|
+
converted = convert(test);
|
21
14
|
}
|
22
15
|
catch (err) {
|
23
16
|
console.log(err.message);
|
17
|
+
process.exit();
|
18
|
+
}
|
19
|
+
console.log(converted);
|
20
|
+
console.log('DM:', converted.toCoordinateFormat(convert.to.DM).replace(/\s/g, '')); // shortened format
|
21
|
+
if (!converted.closeEnough(correctDecimals)) {
|
22
|
+
console.error('!!! conversion is incorrect !!!');
|
24
23
|
}
|
@@ -361,6 +361,13 @@ const otherFormats = [
|
|
361
361
|
verbatimLongitude: `E 18° 57,4583'`,
|
362
362
|
decimalLatitude: 48.51068,
|
363
363
|
decimalLongitude: 18.95764
|
364
|
+
},
|
365
|
+
{
|
366
|
+
verbatimCoordinates: `1.23456, 18.33453`,
|
367
|
+
verbatimLatitude: `1.23456`,
|
368
|
+
verbatimLongitude: `18.33453`,
|
369
|
+
decimalLatitude: 1.23456,
|
370
|
+
decimalLongitude: 18.33453
|
364
371
|
}
|
365
372
|
];
|
366
373
|
function getAllTestFormats() {
|
@@ -26,8 +26,12 @@ function toCoordinateFormat(format) {
|
|
26
26
|
const minutesLatitudeNotTruncated = (absoluteLatitude - degreesLatitude) * 60;
|
27
27
|
const minutesLongitudeNotTruncated = (absoluteLongitude - degreesLongitude) * 60;
|
28
28
|
if (format == 'DM') {
|
29
|
-
|
30
|
-
|
29
|
+
let dmMinsLatitude = round(minutesLatitudeNotTruncated, 3).toFixed(3).padStart(6, '0');
|
30
|
+
let dmMinsLongitude = round(minutesLongitudeNotTruncated, 3).toFixed(3).padStart(6, '0');
|
31
|
+
if (dmMinsLatitude.endsWith('.000') && dmMinsLongitude.endsWith('.000')) {
|
32
|
+
dmMinsLatitude = dmMinsLatitude.replace(/\.000$/, '');
|
33
|
+
dmMinsLongitude = dmMinsLongitude.replace(/\.000$/, '');
|
34
|
+
}
|
31
35
|
result = `${degreesLatitude}° ${dmMinsLatitude}' ${latDir}, ${degreesLongitude}° ${dmMinsLongitude}' ${longDir}`;
|
32
36
|
}
|
33
37
|
if (format == "DMS") {
|
@@ -38,9 +42,9 @@ function toCoordinateFormat(format) {
|
|
38
42
|
const latMinutesString = latMinutes.toString().padStart(2, '0');
|
39
43
|
const longMinutesString = longMinutes.toString().padStart(2, '0');
|
40
44
|
// if they both end in .0 we drop the .0
|
41
|
-
if (latSeconds.endsWith('.0
|
42
|
-
latSeconds = latSeconds.replace(/\.0
|
43
|
-
longSeconds = longSeconds.replace(/\.0
|
45
|
+
if (latSeconds.endsWith('.0') && longSeconds.endsWith('.0')) {
|
46
|
+
latSeconds = latSeconds.replace(/\.0$/, '');
|
47
|
+
longSeconds = longSeconds.replace(/\.0$/, '');
|
44
48
|
}
|
45
49
|
result = `${degreesLatitude}° ${latMinutesString}' ${latSeconds}" ${latDir}, ${degreesLongitude}° ${longMinutesString}' ${longSeconds}" ${longDir}`;
|
46
50
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "geo-coordinates-parser",
|
3
|
-
"version": "1.7.
|
3
|
+
"version": "1.7.3",
|
4
4
|
"description": "A Javascript function for reading a variety of coordinate formats and converting to decimal numbers. Builds on other efforts by returning the verbatim coordinates and the decimal coordinates all in one object.",
|
5
5
|
"type": "module",
|
6
6
|
"main": "./dist/cjs/merge.js",
|