GPS coordinates do not always arrive in the format your application expects. A user might paste a location like this:
40°26′46″N, 79°58′56″W Before using those coordinates in a map or an API request, you may need to convert them into decimal degrees:
40.446111, -79.982222 In this tutorial, we will build a JavaScript converter, validate its inputs, and parse common DMS strings.
Understanding the Conversion
DMS stands for degrees, minutes, and seconds:
- One degree contains 60 minutes.
- One minute contains 60 seconds.
- One degree therefore contains 3,600 seconds.
The conversion formula is:
decimal degrees = degrees + minutes / 60 + seconds / 3600 For example:
40°26′46″N = 40 + 26 / 60 + 46 / 3600 ≈ 40.446111° The hemisphere determines the sign:
| Direction | Coordinate | Sign |
|---|---|---|
| N | Latitude | Positive |
| S | Latitude | Negative |
| E | Longitude | Positive |
| W | Longitude | Negative |
For west longitude, calculate the complete value first and then make it negative:
79°58′56″W = -(79 + 58 / 60 + 56 / 3600) ≈ -79.982222° Create a JavaScript Conversion Function
The following function accepts numeric DMS components and a hemisphere letter:
function dmsToDecimal(degrees, minutes, seconds, direction) { if (![degrees, minutes, seconds].every(Number.isFinite)) { throw new TypeError("DMS components must be finite numbers."); } if (typeof direction !== "string") { throw new TypeError("Direction must be N, S, E, or W."); } const hemisphere = direction.trim().toUpperCase(); if (!["N", "S", "E", "W"].includes(hemisphere)) { throw new RangeError("Direction must be N, S, E, or W."); } if (!Number.isInteger(degrees) || degrees < 0) { throw new RangeError("Degrees must be a non-negative integer."); } if (!Number.isInteger(minutes) || minutes < 0 || minutes >= 60) { throw new RangeError("Minutes must be an integer from 0 to 59."); } if (seconds < 0 || seconds >= 60) { throw new RangeError("Seconds must be at least 0 and less than 60."); } const limit = ["N", "S"].includes(hemisphere) ? 90 : 180; const decimal = degrees + minutes / 60 + seconds / 3600; if (decimal > limit) { throw new RangeError( `Coordinate exceeds the ${limit}-degree limit.` ); } const sign = ["S", "W"].includes(hemisphere) ? -1 : 1; // Normalize zero so the function does not return -0. return decimal === 0 ? 0 : decimal * sign; } This function uses unsigned degrees and a separate direction. Enter 79 and "W", rather than -79 and "W". Keeping one source for the sign avoids ambiguity.
Number.isFinite() checks that each component is a number and rejects NaN and infinity. It also rejects numeric strings, so convert form values explicitly before calling the function.
Example Usage
const latitude = dmsToDecimal(40, 26, 46, "N"); const longitude = dmsToDecimal(79, 58, 56, "W"); console.log(latitude.toFixed(6)); // "40.446111" console.log(longitude.toFixed(6)); // "-79.982222" Decimal seconds work too:
const latitude = dmsToDecimal(40, 26, 46.5, "N"); console.log(latitude.toFixed(6)); // "40.446250" The function returns a number. Use toFixed() when formatting the result for display, and keep the original numeric value for further calculations.
Parse a DMS Coordinate String
If users paste coordinates into a text field, you also need to extract the individual components.
The parser below supports these formats:
40°26′46″N 40° 26' 46" N 40 26 46 N 40°26′46.5″N It requires all three components and a direction at the end.
function parseDms(input) { if (typeof input !== "string") { throw new TypeError("Coordinate must be a string."); } const normalized = input .trim() .replace(/[′’]/g, "'") .replace(/[″”]/g, '"'); const patterns = [ // Symbol-separated: 40° 26' 46" N /^(\d{1,3})\s*°\s*(\d{1,2})\s*'\s*(\d{1,2}(?:\.\d+)?)\s*"\s*([NSEW])$/i, // Space-separated: 40 26 46 N /^(\d{1,3})\s+(\d{1,2})\s+(\d{1,2}(?:\.\d+)?)\s*([NSEW])$/i ]; let match; for (const pattern of patterns) { match = normalized.match(pattern); if (match) break; } if (!match) { throw new Error("Invalid DMS format. Try 40 26 46 N."); } const [, degrees, minutes, seconds, direction] = match; return dmsToDecimal( Number(degrees), Number(minutes), Number(seconds), direction ); } Use it with the conversion function defined earlier:
console.log(parseDms("40°26′46″N").toFixed(6)); // "40.446111" console.log(parseDms("79°58′56″W").toFixed(6)); // "-79.982222" console.log(parseDms("33 51 31 S").toFixed(6)); // "-33.858611" The parser intentionally accepts a limited set of formats. Inputs such as N 40°26′46″, signed degrees, or coordinates with missing seconds require additional parsing rules.
Convert a Latitude and Longitude Pair
For an application, separate latitude and longitude fields make validation easier.
This wrapper verifies that each field uses the correct direction:
function parseDmsPair(latitudeInput, longitudeInput) { if ( typeof latitudeInput !== "string" || typeof longitudeInput !== "string" ) { throw new TypeError("Both coordinates must be strings."); } if (!/[NS]$/i.test(latitudeInput.trim())) { throw new Error("Latitude must end with N or S."); } if (!/[EW]$/i.test(longitudeInput.trim())) { throw new Error("Longitude must end with E or W."); } return { latitude: parseDms(latitudeInput), longitude: parseDms(longitudeInput) }; } Example:
const location = parseDmsPair( "40°26′46″N", "79°58′56″W" ); console.log(location); // { // latitude: 40.44611111111111, // longitude: -79.98222222222222 // } Named properties help keep latitude and longitude distinct when passing the result between functions.
Common Conversion Mistakes
Applying the Negative Sign Only to Degrees
This calculation is incorrect for west longitude:
const longitude = -79 + 58 / 60 + 56 / 3600; It adds the minutes and seconds to a negative degree value. Apply the sign to the entire magnitude instead:
const longitude = -(79 + 58 / 60 + 56 / 3600); Treating DMS as a Decimal Number
This is incorrect:
40°26′46″ → 40.2646 Minutes and seconds are base-60 subdivisions. They must be divided by 60 and 3600, respectively.
Accepting Out-of-Range Values
These inputs should be rejected:
40°60′00″N 40°26′60″N 90°00′01″N 180°00′01″E Latitude can reach 90 degrees and longitude can reach 180 degrees, but neither can exceed its limit. At those boundaries, minutes and seconds must both be zero.
Confusing Format Conversion with CRS Conversion
Converting DMS to decimal degrees changes how a coordinate is written. It does not transform the coordinate into a different coordinate reference system.
If your source data uses a different datum or CRS from your map, changing its notation alone will not resolve the mismatch.
Rounding Too Early
Keep the full numeric result during calculations:
const latitude = parseDms("40°26′46.5″N"); // Format only when displaying the value. const label = latitude.toFixed(6); Showing more decimal places does not improve the accuracy of the original measurement.
Check a Coordinate Before Using It
After converting a coordinate, inspect its position on a map. This can reveal a missing negative sign, swapped fields, or a transcription error that still passes numeric validation.
For a quick visual check, you can use the CoordMap Latitude and Longitude Finder.
The essential steps are straightforward: convert minutes and seconds into fractions of a degree, apply the hemisphere sign to the complete result, and validate the coordinate before using it.
