geo-coordinates-parser 1.3.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Geo Coordinates Parser
2
2
 
3
- A Javascript function for reading a variety of coordinate formats and converting to decimal latitude and longitude. Builds on other efforts for convenience by returning the verbatim coordinates and the decimal coordinates all in one object. Can be used to extract coordinates from longer strings. Also includes a function to test existing decimal coordinates against those from the converter.
3
+ A Javascript function for reading a variety of coordinate formats and converting to decimal latitude and longitude. Builds on previous efforts and returns the verbatim coordinates and the decimal coordinates together in one object for convenience. Can be used to extract coordinates from longer strings. Also includes a function to test existing decimal coordinates against those from the converter.
4
4
 
5
- ##If you like this package please [star it on GitHub](https://github.com/ianengelbrecht/geo-coordinates-parser)
5
+ ##If you like this tool please [star it on GitHub](https://github.com/ianengelbrecht/geo-coordinates-parser)
6
6
 
7
7
  ### Installation
8
8
  ```
@@ -15,7 +15,7 @@ const convert = require('geo-coordinates-parser');
15
15
  ```
16
16
  OR
17
17
  ```js
18
- import convert from 'geo-coordinates-parser' //ES6
18
+ import convert from 'geo-coordinates-parser' //ES6, if you're using a bundler
19
19
  ```
20
20
  THEN
21
21
  ```js
@@ -24,7 +24,7 @@ try {
24
24
  converted = convert('40° 26.7717, -79° 56.93172');
25
25
  }
26
26
  catch {
27
- //we get here if the string is not valid coordinates
27
+ /*we get here if the string is not valid coordinates or format is inconsistent between lat and long*/
28
28
  }
29
29
 
30
30
  ```
@@ -39,7 +39,7 @@ catch{
39
39
  //coordinates not valid
40
40
  }
41
41
  ```
42
- THEN
42
+ ALSO
43
43
  ```js
44
44
  converted.decimalLatitude; // 40.446195 ✓
45
45
  converted.decimalLongitude; // -79.948862 ✓
@@ -48,14 +48,14 @@ converted.verbatimLongitude; // '-79° 56.93172' ✓
48
48
  ```
49
49
  The returned object includes properties verbatimCoordinates, verbatimLatitude, verbatimLongitude, decimalLatitude, decimalLatitude, and decimalCoordinates.
50
50
 
51
- Sometimes we may want to validate existing decimal coordinates against those returned from the converter to find errors. Because we're working with decimal numbers we must settle for values that are close enough (in this case the same up to six decimal places).
51
+ ### Validating other conversions
52
+ Sometimes we may want to validate existing decimal coordinates against those returned from the converter to find errors. Because we're working with decimal numbers we must settle for values that are close enough (in this case equal up to six decimal places).
52
53
 
53
54
  ```js
54
- converted.closeEnough(yourDecimalCoordinatesToTest) //must be a string separated by ,
55
+ converted.closeEnough(yourDecimalCoordinatesToValidate) //must be a numbers separated by ,
55
56
  ```
56
57
 
57
58
  ### Supported formats
58
-
59
59
  All formats (except the 'exotic formats') covered by [npm coordinate-parser](https://www.npmjs.com/package/coordinate-parser) and the [coordinate regex in this GitHub Gist](https://gist.github.com/moole/3707127/337bd31d813a10abcf55084381803e5bbb0b20dc), including the following:
60
60
  - -23.3245° S / 28.2344° E
61
61
  - 27deg 15min 45.2sec S 18deg 32min 53.7sec E
@@ -71,14 +71,19 @@ Formats used for testing can be be accessed with:
71
71
  convert.formats
72
72
  ```
73
73
 
74
- **Please add coordinate formats that throw an error in the Github Issues.**
74
+ **<span style="color:red">Please add coordinate formats that throw an error in the Github Issues.</span>**
75
+
76
+ **<span style="color:red">Note that formats like 24.56S 26.48E are treated as degrees and minutes! And 24.0, 26.0 is treated as an error. If you don't want this behaviour you need to catch these cases with your own code before you use convert.</span>**
75
77
 
76
78
  ### Want to use it in the browser?
77
79
  A ready bundled script is available in the source code, in the bundle directory, named geocoordsparser.js. [Download](https://stackoverflow.com/a/13593430/3210158), include it in a script tag in your html, and you'll have a function called `convert()` available in your environment.
78
80
 
79
- ### Other implementations
80
- There is an [MS Excel plugin here](http://bit.ly/convertcoords). See the README for instructions.
81
- More to come...
81
+ ### Convert back to standard formats
82
+ Sometimes we might want to convert back to more traditional formats for representing coordinates, such as DMS or DM. This can be useful for standardizing coordinates. The convert function has an enum to help.
83
+
84
+ ```js
85
+ converted.toCoordinateFormat(convert.to.DMS) /// '40° 26.771" N, 79° 56.932" W' ✓
86
+ ```
82
87
 
83
88
  ### License
84
89
  MIT Licence
@@ -1 +1 @@
1
- !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).convert=t()}}(function(){function t(t){var e=t.filter(function(t){return!(!t||""==t)});if(e.shift(),e.length%2>0)return!1;for(var r=/^[-+]?(\d+|\d+\.\d*|\d*\.\d+)$/,i=/[A-Za-z]+/,a=e.length/2,n=!0,s=0;s<a;s++)if(r.test(e[s])!=r.test(e[s+a])||i.test(e[s])!=i.test(e[s+a])){n=!1;break}return n}function e(t,e){var r=Math.abs(t-e);return diff=Number(r.toFixed(6)),diff<=1e-5}function r(t){if(t.includes(",")){var r=t.split(",");if(NaN==Number(r[0])||NaN==Number(r[1]))throw new Error("coords are not valid decimals");return e(this.decimalLatitude,Number(r[0]))&&e(this.decimalLongitude,r[1])}throw new Error("coords being tested must be separated by a comma")}var i=/(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))([\u2022\xba\xb0]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))([\u2022\xba\xb0]?)[\s]*(EAST|WEST|[EW])?/i,a=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(EAST|WEST|[EW])?/i,n=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)?[\ \t]*(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)[\ \t]*(EAST|WEST|[EW])?/i,s=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*([\u2022\xba\xb0\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['\u2032\xb4\u2019\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|\u2032\u2032|\u2019\u2019|\xb4\xb4|["\u2033\u201d\.])?[\ \t]*(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*([\u2022\xba\xb0\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['\u2032\xb4\u2019\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|\u2032\u2032|\xb4\xb4|\u2019\u2019|["\u2033\u201d\.])?[\ \t]*(EAST|WEST|[EW])?/i;return function(e,o){o||(o=5),e=e.replace(/\s\s+/g," ").trim();var d=null,u=null,f="",l="",E=[],S=!1;if(i.test(e)){if(!(S=t(E=i.exec(e))))throw new Error("invalid decimal coordinate format");d=E[2],u=E[6],d.includes(",")&&d.replace(",","."),u.includes(",")&&u.replace(",","."),E[1]?(f=E[1],l=E[5]):E[4]&&(f=E[4],l=E[8])}else if(a.test(e)){if(!(S=t(E=a.exec(e))))throw new Error("invalid DMS coordinates format");d=Math.abs(parseInt(E[2])),E[4]&&(d+=E[4]/60),E[6]&&(d+=E[6]/3600),parseInt(E[2])<0&&(d*=-1),u=Math.abs(parseInt(E[9])),E[11]&&(u+=E[11]/60),E[13]&&(u+=E[13]/3600),parseInt(E[9])<0&&(u*=-1),E[1]?(f=E[1],l=E[8]):E[7]&&(f=E[7],l=E[14])}else if(n.test(e)){if(!(S=t(E=n.exec(e))))throw new Error("invalid DMS coordinates format");d=Math.abs(parseInt(E[2])),E[4]&&(d+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(d+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(d*=-1),u=Math.abs(parseInt(E[10])),E[12]&&(u+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(u+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(u*=-1),E[1]?(f=E[1],l=E[9]):E[8]&&(f=E[8],l=E[16])}else if(s.test(e)){if(!(S=t(E=s.exec(e))))throw new Error("invalid coordinates format");d=Math.abs(parseInt(E[2])),E[4]&&(d+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(d+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(d*=-1),u=Math.abs(parseInt(E[10])),E[12]&&(u+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(u+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(u*=-1),E[1]?(f=E[1],l=E[9]):E[8]&&(f=E[8],l=E[16])}if(Math.abs(u)>=180)throw new Error("invalid longitude value");if(S){var b,c,N=/S|SOUTH/i;N.test(f)&&d>0&&(d*=-1),(N=/W|WEST/i).test(l)&&u>0&&(u*=-1);var T=e.match(/[,/\u0020]/g);if(null==T){var m=Math.floor(e.length/2);b=e.substring(0,m).trim(),c=e.substring(m).trim()}else{var h=0;if(0==(m=T.length%2==1?Math.floor(T.length/2):T.length/2-1))h=e.indexOf(T[0]),b=e.substring(0,h).trim(),c=e.substring(h+1).trim();else{for(var p=0,x=0;p<=m;)x=(h=e.indexOf(T[p],x))+1,p++;b=e.substring(0,h).trim(),c=e.substring(h+1).trim()}}return isNaN(d)&&d.includes(",")&&(d=d.replace(",",".")),d=Number(Number(d).toFixed(o)),isNaN(u)&&u.includes(",")&&(u=u.replace(",",".")),{verbatimCoordinates:e,verbatimLatitude:b,verbatimLongitude:c,decimalLatitude:d,decimalLongitude:u=Number(Number(u).toFixed(o)),decimalCoordinates:`${d},${u}`,closeEnough:r}}throw new Error("coordinates pattern match failed")}});
1
+ !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).convert=t()}}(function(){function t(t,e,r){const i=Number(t);let a;a=r?i>=0?"N":"S":i>=0?"E":"W";const n=Math.abs(i),o=Math.floor(n),s=60*(n-o);if("DM"==e)return`${o}\xb0 ${s.toFixed(3).replace(/\.0+$/,"")}' ${a}`;const d=Math.floor(s);return`${o}\xb0 ${d}' ${(60*(s-d)).toFixed(1).replace(/\.0$/,"")}" ${a}`}var e=function(e){if(!["DMS","DM"].includes(e))throw new Error("invalid format specified");if(this.decimalCoordinates&&this.decimalCoordinates.trim()){const r=this.decimalCoordinates.split(",").map(t=>t.trim());return`${t(r[0],e,!0)}, ${t(r[1],e,!1)}`}throw new Error("no decimal coordinates to convert")};function r(t,r){r||(r=5),t=t.replace(/\s\s+/g," ").trim();var a=null,l=null,f="",c="",E=[],S=!1;if(o.test(t)){if(!(S=i(E=o.exec(t))))throw new Error("invalid decimal coordinate format");a=E[2],l=E[6],a.includes(",")&&(a=a.replace(",",".")),l.includes(",")&&(l=l.replace(",",".")),E[1]?(f=E[1],c=E[5]):E[4]&&(f=E[4],c=E[8])}else if(s.test(t)){if(!(S=i(E=s.exec(t))))throw new Error("invalid DMS coordinates format");a=Math.abs(parseInt(E[2])),E[4]&&(a+=E[4]/60),E[6]&&(a+=E[6]/3600),parseInt(E[2])<0&&(a*=-1),l=Math.abs(parseInt(E[9])),E[11]&&(l+=E[11]/60),E[13]&&(l+=E[13]/3600),parseInt(E[9])<0&&(l*=-1),E[1]?(f=E[1],c=E[8]):E[7]&&(f=E[7],c=E[14])}else if(d.test(t)){if(!(S=i(E=d.exec(t))))throw new Error("invalid DMS coordinates format");a=Math.abs(parseInt(E[2])),E[4]&&(a+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(a+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(a*=-1),l=Math.abs(parseInt(E[10])),E[12]&&(l+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(l+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(l*=-1),E[1]?(f=E[1],c=E[9]):E[8]&&(f=E[8],c=E[16])}else if(u.test(t)){if(!(S=i(E=u.exec(t))))throw new Error("invalid coordinates format");a=Math.abs(parseInt(E[2])),E[4]&&(a+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(a+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(a*=-1),l=Math.abs(parseInt(E[10])),E[12]&&(l+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(l+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(l*=-1),E[1]?(f=E[1],c=E[9]):E[8]&&(f=E[8],c=E[16])}if(Math.abs(l)>=180)throw new Error("invalid longitude value");if(S){var b=/S|SOUTH/i;b.test(f)&&a>0&&(a*=-1),(b=/W|WEST/i).test(c)&&l>0&&(l*=-1);var m,N,h=E[0].trim(),T=h.match(/[,/;\u0020]/g);if(null==T){var p=Math.floor(t.length/2);m=h.substring(0,p).trim(),N=h.substring(p).trim()}else{var x=0;if(0==(p=T.length%2==1?Math.floor(T.length/2):T.length/2-1))x=h.indexOf(T[0]),m=h.substring(0,x).trim(),N=h.substring(x+1).trim();else{for(var M=0,v=0;M<=p;)v=(x=h.indexOf(T[M],v))+1,M++;m=h.substring(0,x).trim(),N=h.substring(x+1).trim()}}return isNaN(a)&&a.includes(",")&&(a=a.replace(",",".")),a=Number(Number(a).toFixed(r)),isNaN(l)&&l.includes(",")&&(l=l.replace(",",".")),l=Number(Number(l).toFixed(r)),Object.freeze({verbatimCoordinates:h,verbatimLatitude:m,verbatimLongitude:N,decimalLatitude:a,decimalLongitude:l,decimalCoordinates:`${a},${l}`,closeEnough:n,toCoordinateFormat:e})}throw new Error("coordinates pattern match failed")}function i(t){if(!isNaN(t[0]))return!1;var e=t.filter(t=>t);if(e.shift(),e.length%2>0)return!1;for(var r=/^[-+]?(\d+|\d+\.\d*|\d*\.\d+)$/,i=/[A-Za-z]+/,a=e.length/2,n=!0,o=0;o<a;o++)if(r.test(e[o])!=r.test(e[o+a])||i.test(e[o])!=i.test(e[o+a])){n=!1;break}return n}function a(t,e){var r=Math.abs(t-e);return diff=Number(r.toFixed(6)),diff<=1e-5}function n(t){if(t.includes(",")){var e=t.split(",");if(NaN==Number(e[0])||NaN==Number(e[1]))throw new Error("coords are not valid decimals");return a(this.decimalLatitude,Number(e[0]))&&a(this.decimalLongitude,e[1])}throw new Error("coords being tested must be separated by a comma")}var o=/(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))([\u2022\xba\xb0]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/;]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))([\u2022\xba\xb0]?)[\s]*(EAST|WEST|[EW])?/i,s=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/;][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(EAST|WEST|[EW])?/i,d=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)?[\ \t]*(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/;][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)[\ \t]*(EAST|WEST|[EW])?/i,u=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*([\u2022\xba\xb0\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['\u2032\xb4\u2019\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|\u2032\u2032|\u2019\u2019|\xb4\xb4|["\u2033\u201d\.])?[\ \t]*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*([\u2022\xba\xb0\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['\u2032\xb4\u2019\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|\u2032\u2032|\xb4\xb4|\u2019\u2019|["\u2033\u201d\.])?[\ \t]*(EAST|WEST|[EW])?/i;const l=Object.freeze({DMS:"DMS",DM:"DM"});return r.to=l,r});
@@ -4,5 +4,7 @@ Inside /bundle run the following
4
4
 
5
5
  browserify -p tinyify ../converter.js --standalone convert > geocoordsparser.js
6
6
 
7
+ Then npm publish
8
+
7
9
  geocoordsparser.js can then be included in <script> tags
8
10
  This puts a function called convert into the global environment
package/converter.js CHANGED
@@ -1,7 +1,16 @@
1
1
  //function for converting coordinates from a string to decimal and verbatim
2
- //TODO, add number of decimal places to return
2
+
3
+ const toCoordinateFormat = require('./toCoordinateFormat.js')
4
+
5
+ /**
6
+ * Function for converting coordinates in a variety of formats to decimal coordinates
7
+ * @param {string} coordsString The coordinates string to convert
8
+ * @param {number} decimalPlaces The number of decimal places for converted coordinates; default is 5
9
+ * @returns {object} { verbatimCoordinates, decimalCoordinates, decimalLatitude, decimalLongitude }
10
+ */
3
11
  function converter(coordsString, decimalPlaces) {
4
12
 
13
+ //TODO add exact match to entered string, so that it can be used to filter out superflous text around it
5
14
  if(!decimalPlaces) {
6
15
  decimalPlaces = 5
7
16
  }
@@ -24,10 +33,10 @@ function converter(coordsString, decimalPlaces) {
24
33
 
25
34
  //need to fix if there are ','s instead of '.'
26
35
  if(ddLat.includes(',')) {
27
- ddLat.replace(',','.');
36
+ ddLat = ddLat.replace(',','.');
28
37
  }
29
38
  if(ddLng.includes(',')) {
30
- ddLng.replace(',', '.');
39
+ ddLng = ddLng.replace(',', '.');
31
40
  }
32
41
 
33
42
  //get directions
@@ -193,7 +202,7 @@ function converter(coordsString, decimalPlaces) {
193
202
  var verbatimLat
194
203
  var verbatimLng
195
204
 
196
- var sepChars = /[,/\u0020]/g //comma, forward slash and spacebar
205
+ var sepChars = /[,/;\u0020]/g //comma, forward slash and spacebar
197
206
  var seps = verbatimCoordinates.match(sepChars)
198
207
 
199
208
  if (seps == null) {
@@ -254,15 +263,16 @@ function converter(coordsString, decimalPlaces) {
254
263
 
255
264
  ddLng = Number(Number(ddLng).toFixed(decimalPlaces))
256
265
 
257
- return {
266
+ return Object.freeze({
258
267
  verbatimCoordinates,
259
268
  verbatimLatitude: verbatimLat,
260
269
  verbatimLongitude: verbatimLng,
261
270
  decimalLatitude: ddLat,
262
271
  decimalLongitude: ddLng,
263
272
  decimalCoordinates: `${ddLat},${ddLng}`,
264
- closeEnough: coordsCloseEnough
265
- }
273
+ closeEnough: coordsCloseEnough,
274
+ toCoordinateFormat
275
+ })
266
276
  }
267
277
  else {
268
278
  throw new Error("coordinates pattern match failed")
@@ -340,12 +350,19 @@ function coordsCloseEnough(coordsToTest) {
340
350
  }
341
351
 
342
352
  //Coordinates pattern matching regex
343
- var dd_re = /(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(EAST|WEST|[EW])?/i;
353
+ var dd_re = /(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/;]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(EAST|WEST|[EW])?/i;
344
354
  //degrees minutes seconds with '.' as separator - gives array with 15 values
345
- var dms_periods = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(EAST|WEST|[EW])?/i;
355
+ var dms_periods = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/;][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(EAST|WEST|[EW])?/i;
346
356
  //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
347
- var dms_abbr = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)?[\ \t]*(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)[\ \t]*(EAST|WEST|[EW])?/i;
357
+ var dms_abbr = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)?[\ \t]*(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/;][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)[\ \t]*(EAST|WEST|[EW])?/i;
348
358
  //everything else - gives array of 17 values
349
- var coords_other = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*([•º°\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['′´’\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|′′|’’|´´|["″”\.])?[\ \t]*(NORTH|SOUTH|[NS])?(?:\s*[,/]\s*|\s*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*([•º°\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['′´’\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|′′|´´|’’|["″”\.])?[\ \t]*(EAST|WEST|[EW])?/i;
359
+ var coords_other = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*([•º°\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['′´’\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|′′|’’|´´|["″”\.])?[\ \t]*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*([•º°\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['′´’\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|′′|´´|’’|["″”\.])?[\ \t]*(EAST|WEST|[EW])?/i;
360
+
361
+ const to = Object.freeze({
362
+ DMS: 'DMS',
363
+ DM: 'DM'
364
+ })
365
+
366
+ converter.to = to
350
367
 
351
368
  module.exports = converter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geo-coordinates-parser",
3
- "version": "1.3.1",
3
+ "version": "1.4.2",
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
  "main": "merge.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -25,9 +25,9 @@ testFormats.some(t => { //.some so we can break
25
25
  //check the verbatim coords are correct
26
26
  if(converted.verbatimLatitude != t.verbatimLatitude || converted.verbatimLongitude != t.verbatimLongitude) {
27
27
  console.log("Error in verbatim extraction")
28
- console.log(t.verbatimCoordinates)
29
- console.log(t.verbatimLatitude)
30
- console.log(t.verbatimLongitude)
28
+ console.log('For', t.verbatimCoordinates)
29
+ console.log('got', converted.verbatimLatitude, 'should be ', t.verbatimLatitude)
30
+ console.log('got', converted.verbatimLongitude, 'should be', t.verbatimLongitude)
31
31
  allPassed = false;
32
32
  return true
33
33
  }
@@ -0,0 +1,8 @@
1
+ const toCoordinateFormat = require('./toCoordinateFormat.js')
2
+
3
+ let test = {
4
+ decimalCoordinates: '-234.3456, 28.92435',
5
+ toCoordinateFormat
6
+ }
7
+
8
+ console.log(test.toCoordinateFormat('DMS'))
package/testIndividual.js CHANGED
@@ -1,8 +1,20 @@
1
1
  const convert = require('./converter')
2
- const test = 'Between Sannieshof and Bessiesvlei. 26.4558°S 25.8644°E.'
2
+ const test = '27,71372° S 23,07771° E'
3
+
3
4
  try{
4
5
  let converted = convert(test)
5
6
  console.log(converted)
7
+ console.log(converted.toCoordinateFormat(convert.to.DM))
8
+
9
+ //and just to make sure it's frozen
10
+ let previous = converted.decimalLatitude
11
+ converted.decimalLatitude = 24
12
+ if(converted.decimalLatitude === previous) {
13
+ console.log('the result is frozen')
14
+ }
15
+ else {
16
+ console.error('!!!The result is not frozen!!!!')
17
+ }
6
18
  }
7
19
  catch(err){
8
20
  console.log(err.message)
package/testformats.js CHANGED
@@ -131,6 +131,11 @@ var coordsParserFormats = [
131
131
  verbatimCoordinates: '40° 7.38, -74° 7.38',
132
132
  verbatimLatitude: '40° 7.38',
133
133
  verbatimLongitude: '-74° 7.38'
134
+ },
135
+ {
136
+ verbatimCoordinates: '40 7 22.8; -74 7 22.8', //semicolon separator
137
+ verbatimLatitude: '40 7 22.8',
138
+ verbatimLongitude: '-74 7 22.8'
134
139
  }
135
140
  ]
136
141
 
@@ -213,6 +218,13 @@ var coordsRegexFormats = [
213
218
  verbatimLongitude: '-79.948862',
214
219
  decimalLatitude: 40.446195,
215
220
  decimalLongitude: -79.948862
221
+ },
222
+ {
223
+ verbatimCoordinates: '40.123256; -74.123256', //testing semicolon
224
+ verbatimLatitude: '40.123256',
225
+ verbatimLongitude: '-74.123256',
226
+ decimalLatitude: 40.123256,
227
+ decimalLongitude: -74.123256
216
228
  }
217
229
  ]
218
230
 
@@ -0,0 +1,52 @@
1
+
2
+ //borrowed from https://www.codegrepper.com/code-examples/javascript/javascript+converting+latitude+longitude+to+gps+coordinates
3
+
4
+ /**
5
+ * Converts decimalCoordinates to other formats commonly used
6
+ * @param {*} format Either DMS or DM
7
+ */
8
+ function toCoordinateFormat(format) {
9
+
10
+ if(!['DMS', 'DM'].includes(format)) throw new Error('invalid format specified')
11
+
12
+ if(this.decimalCoordinates && this.decimalCoordinates.trim()) {
13
+ const parts = this.decimalCoordinates.split(',').map(x => x.trim())
14
+ const convertedLat = convert(parts[0], format, true)
15
+ const convertedLong = convert(parts[1], format, false)
16
+ return `${convertedLat}, ${convertedLong}`
17
+ }
18
+ else {
19
+ throw new Error('no decimal coordinates to convert')
20
+ }
21
+ }
22
+
23
+ //assumes everything is valid...
24
+ function convert(coordString, format, isLatitude) {
25
+
26
+ const coord = Number(coordString)
27
+
28
+ let direction
29
+ if (isLatitude) {
30
+ direction = coord >= 0 ? "N" : "S";
31
+ }
32
+ else {
33
+ direction = coord >= 0 ? "E" : "W";
34
+ }
35
+
36
+ const absolute = Math.abs(coord);
37
+
38
+ const degrees = Math.floor(absolute);
39
+ const minutesNotTruncated = (absolute - degrees) * 60;
40
+
41
+ if(format == 'DM') {
42
+ return `${degrees}° ${minutesNotTruncated.toFixed(3).replace(/\.0+$/, '')}' ${direction}`;
43
+ }
44
+
45
+ //else
46
+ const minutes = Math.floor(minutesNotTruncated);
47
+ const seconds = ((minutesNotTruncated - minutes) * 60).toFixed(1).replace(/\.0$/, '');
48
+
49
+ return `${degrees}° ${minutes}' ${seconds}" ${direction}`;
50
+ }
51
+
52
+ module.exports = toCoordinateFormat