Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fat deggree format #3

Merged
merged 2 commits into from
Sep 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ const successCases: Case[] = [
{ title: 'Japanese Postfix, order: 西 -> 南', input: '西135.6789, 南35.1234', output: [{ lat: -35.1234, lng: -135.6789 }] },
{ title: 'Japanese Postfix, order: 北 -> 東, overflow +1π', input: '北35.1234, 東315.6789', output: [{ lat: 35.1234, lng: -44.3211 }] },

// DD.DDD°
{ title: 'DD.DDD°, order: N -> E', input: 'N35.1234°, E135.6789°', output: [{ lat: 35.1234, lng: 135.6789 }] },

// DD°MM'SS"
{ title: 'DD°MM\'SS", order: lat -> lng', input: '35°12\'34", 135°43\'21.01"', output: [{ lat: 35 + 12 / 60 + 34 / 3600, lng: 135 + 43 / 60 + 21.01 / 3600 }] },
{ title: 'DD°MM\'SS", order: lng -> lat', input: '135°43\'21.01", 35°12\'34"', output: [{ lat: 35 + 12 / 60 + 34 / 3600, lng: 135 + 43 / 60 + 21.01 / 3600 }] },
Expand Down Expand Up @@ -115,6 +118,10 @@ const successCases: Case[] = [
{ title: 'https://ja.wikipedia.org/wiki/諫早湾', input: '北緯32度53分9.35秒 東経130度11分9.34秒', output: [{ lat: 32 + 53 / 60 + 9.35 / 3600, lng: 130 + 11 / 60 + 9.34 / 3600 }] },
{ title: 'https://en.wikipedia.org/wiki/Canada', input: '45°24′N 75°40′W', output: [{ lat: 45 + 24 / 60, lng: -1 * (75 + 40 / 60) }] },

// https://github.com/geolonia/normalize-any-latlng/issues/2
{ title: '「度分秒.秒」 type', input: '北緯360613.58925 東経1400516.27815', output: [ { lat: 36 + 6 / 60 + 13.58925 / 3600, lng: 140 + 5 / 60 + 16.27815 / 3600 } ] },
{ title: '「度分秒.秒」 type', input: '南緯360613.58925 西経1400516.27815', output: [ { lat: -36 - 6 / 60 - 13.58925 / 3600, lng: -140 - 5 / 60 - 16.27815 / 3600 } ] },

// errors
{ title: 'invalid latlng', input: 'aaa bbb ccc', output: [{lat: null, lng: null}] },
];
Expand Down
9 changes: 9 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isFatDegreeFormat } from './lib';

export type NormalizationResult = {
lat: number | null
lng: number | null
Expand Down Expand Up @@ -148,6 +150,13 @@ export const normalize: Normalize = (latlngStr) => {
}
}

const latInFatDegree = lat !== null ? isFatDegreeFormat(lat) : false;
const lngInFatDegree = lng !== null ? isFatDegreeFormat(lng) : false;
if (latInFatDegree && lngInFatDegree) {
lat = latInFatDegree.degree + latInFatDegree.minute / 60 + latInFatDegree.second / 3600;
lng = lngInFatDegree.degree + lngInFatDegree.minute / 60 + lngInFatDegree.second / 3600;
}

if ((typeof lat === 'number' && (lat < -90 || lat > 90) || Number.isNaN(lat))) {
lat = null;
}
Expand Down
77 changes: 77 additions & 0 deletions src/lib.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { isFatDegreeFormat } from './lib';

test('should be interpreted as DMS', () => {
const input = 360613.58925;
const output = isFatDegreeFormat(input);
expect(output).toStrictEqual({
degree: 36,
minute: 6,
second: 13.58925,
});
});

test('should be interpreted as DMS', () => {
const input = -360613.58925;
const output = isFatDegreeFormat(input);
expect(output).toStrictEqual({
degree: -36,
minute: -6,
second: -13.58925,
});
});

test('should be interpreted as DMS', () => {
const input = 1400516.27815;
const output = isFatDegreeFormat(input);
expect(output).toStrictEqual({
degree: 140,
minute: 5,
second: 16.27815,
});
});

test('should be interpreted as DMS', () => {
const input = -1400516.27815;
const output = isFatDegreeFormat(input);
expect(output).toStrictEqual({
degree: -140,
minute: -5,
second: -16.27815,
});
});

test('too big number should not be interpreted as DMS', () => {
const input = 12345654.25;
const output = isFatDegreeFormat(input);
expect(output).toBe(false);
});

test('minute < 1 should not be interpreted as DMS', () => {
const input = 58.9234;
const output = isFatDegreeFormat(input);
expect(output).toBe(false);
});

test('minute > -1 should not be interpreted as DMS', () => {
const input = -58.9234;
const output = isFatDegreeFormat(input);
expect(output).toBe(false);
});

test('too small number should not be interpreted as DMS', () => {
const input = -12345654.25;
const output = isFatDegreeFormat(input);
expect(output).toBe(false);
});

test('minute over 59 should not be interpreted as DMS', () => {
const input = 366059.58925;
const output = isFatDegreeFormat(input);
expect(output).toBe(false);
});

test('second over 59 should not be interpreted as DMS', () => {
const input = 365960.58925;
const output = isFatDegreeFormat(input);
expect(output).toBe(false);
});
22 changes: 22 additions & 0 deletions src/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* We call numbers like 360613.58925 as fat degree format.
* It should be interpreted as 36°06'13.58925".
*/
export const isFatDegreeFormat = (deg: number) => {
if (Math.abs(deg) > 1800000) return false;

const unit = deg < 0 ? -1 : 1;

const [integer, decimal = ''] = Math.abs(deg).toString().split('.');

const numberStr = integer.padStart(7, '0');
const degree = unit * parseInt(numberStr.slice(0, 3));
const minute = unit * parseInt(numberStr.slice(3, 5));
const second = unit * (parseInt(numberStr.slice(5, 7)) + parseInt(decimal) / 100000);
if (
Math.abs(minute) < 1 ||
Math.abs(minute) > 59 ||
Math.abs(second) > 60
) return false;
return { degree, minute, second };
};