DEV Community

Luo Atlas
Luo Atlas

Posted on

How to Convert DMS to Decimal Degrees in JavaScript

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
Enter fullscreen mode Exit fullscreen mode

Before using those coordinates in a map or an API request, you may need to convert them into decimal degrees:

40.446111, -79.982222
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

For example:

40°26′46″N
= 40 + 26 / 60 + 46 / 3600
≈ 40.446111°
Enter fullscreen mode Exit fullscreen mode

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°
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Decimal seconds work too:

const latitude = dmsToDecimal(40, 26, 46.5, "N");
console.log(latitude.toFixed(6)); // "40.446250"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
  );
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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)
  };
}
Enter fullscreen mode Exit fullscreen mode

Example:

const location = parseDmsPair(
  "40°26′46″N",
  "79°58′56″W"
);

console.log(location);
// {
//   latitude: 40.44611111111111,
//   longitude: -79.98222222222222
// }
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Treating DMS as a Decimal Number

This is incorrect:

40°26′46″ → 40.2646
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)