# parse-dms
[](#contributors-)
[](https://crates.io/crates/parse-dms)
[](https://docs.rs/parse-dms)
[](https://github.com/trananhtung/parse-dms/actions/workflows/ci.yml)
[](#license)
**Parse a coordinate string into decimal latitude/longitude.**
`parse-dms` turns a human-written geographic coordinate — in degrees/minutes/seconds or
decimal degrees, with optional hemisphere letters — into decimal degrees:
```rust
use parse_dms::{parse_dms, Dms};
let c = parse_dms("59°12'7.7\"N 002°15'39.6\"W").unwrap();
assert_eq!(c, Dms::Coordinates { lat: Some(59.20213888888889), lon: Some(-2.261) });
```
A faithful Rust port of the [`parse-dms`](https://www.npmjs.com/package/parse-dms) npm
package.
- Accepts varied separators: `°º:d` for degrees, `'’‘′:` for minutes, `"″''` for seconds
- Infers latitude/longitude from hemisphere letters (`N`/`S`/`E`/`W`), or — for two
hemisphere-less coordinates — from their order (first = lat, second = lon)
- Differential-tested against the reference `parse-dms` implementation
## Install
```toml
[dependencies]
parse-dms = "0.1"
```
## Usage
```rust
use parse_dms::{parse_dms, Dms};
// DMS with hemispheres
assert_eq!(
parse_dms("48°51'24\"N, 2°21'03\"E").unwrap(),
Dms::Coordinates { lat: Some(48.85666666666667), lon: Some(2.3508333333333336) }
);
// Decimal pair, order-inferred
assert_eq!(
parse_dms("40.7128, -74.0060").unwrap(),
Dms::Coordinates { lat: Some(40.7128), lon: Some(-74.006) }
);
// Single coordinate with a hemisphere → only that axis is set
assert_eq!(parse_dms("51 N").unwrap(), Dms::Coordinates { lat: Some(51.0), lon: None });
// A bare value with no hemisphere → a single decimal number
assert_eq!(parse_dms("-51.5").unwrap(), Dms::Decimal(-51.5));
// Out-of-range and unparseable inputs error
assert!(parse_dms("181").is_err());
assert!(parse_dms("nonsense").is_err());
```
## Return value
`parse_dms` returns a [`Dms`]:
- `Dms::Decimal(f64)` — a single coordinate that had no hemisphere letter.
- `Dms::Coordinates { lat, lon }` — otherwise; each field is `None` when the input didn't
provide that component.
Components are validated: degrees `0..=180`, minutes and seconds `0..=60`.
## Compatibility note
This is a faithful port, including the reference's quirks — for example a leading
hemisphere letter triggers a one-character overlap when scanning for a second coordinate
(`parse_dms("n51")` yields `{ lat: 51, lon: 1 }`, matching the npm package). Lowercase
hemisphere letters are, as in the reference, not treated as hemispheres.
## Contributors ✨
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the [emoji key](https://allcontributors.org/docs/en/emoji-key) for how each contribution is recognized, and open a PR or issue to get involved.
Thanks goes to these wonderful people:
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/trananhtung"><img src="https://avatars.githubusercontent.com/u/30992229?v=4?s=100" width="100px;" alt="Tung Tran"/><br /><sub><b>Tung Tran</b></sub></a><br /><a href="https://github.com/trananhtung/./commits?author=trananhtung" title="Code">💻</a> <a href="#maintenance-trananhtung" title="Maintenance">🚧</a></td>
</tr>
</tbody>
</table>
## License
Licensed under either of [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE) at your option.