# HG changeset patch
# User jgindin@chagall
# Date 1644203500 18000
# Sun Feb 06 22:11:40 2022 -0500
# Node ID 8f46fef64c21ed8c259a254316a7446d2abdbccd
# Parent 81aa109a82877d30a26c6fc2d71859174e09a0e2
Refactor LatitudeLongitudeParser to be simpler and easier to move to kotlin.
diff --git a/Android/src/main/java/com/gindin/zmanim/android/ZmanimActivity.java b/Android/src/main/java/com/gindin/zmanim/android/ZmanimActivity.java
--- a/Android/src/main/java/com/gindin/zmanim/android/ZmanimActivity.java
+++ b/Android/src/main/java/com/gindin/zmanim/android/ZmanimActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021. Jay R. Gindin
+ * Copyright (c) 2022. Jay R. Gindin
*/
package com.gindin.zmanim.android;
@@ -517,10 +517,12 @@
// The user didn't grant our permissions. The app can work, but they'll have to tell us where we are.
if ( ( lastKnownLocation != null ) && !lastKnownLocation.isInvalid ) {
- LatitudeLongitudeParser.Holder holder = LatitudeLongitudeParser.parse( Double.toString( lastKnownLocation.getLatitude() ), "", "", LatitudeLongitudeParser.Direction.NORTH );
+ LatitudeLongitudeParser holder = LatitudeLongitudeParser.latitude(
+ LatitudeLongitudeParser.Direction.NORTH, Double.toString( lastKnownLocation.getLatitude() ), "", "" );
String latitude = holder.toFullString( false );
- holder = LatitudeLongitudeParser.parse( Double.toString( lastKnownLocation.getLongitude() ), "", "", LatitudeLongitudeParser.Direction.EAST );
+ holder = LatitudeLongitudeParser.longitude(
+ LatitudeLongitudeParser.Direction.EAST, Double.toString( lastKnownLocation.getLongitude() ), "", "" );
String longitude = holder.toFullString( false );
locationManagementPrefs
diff --git a/Android/src/main/java/com/gindin/zmanim/android/location/acquirers/LatitudeLongitudeLocationAcquirer.java b/Android/src/main/java/com/gindin/zmanim/android/location/acquirers/LatitudeLongitudeLocationAcquirer.java
--- a/Android/src/main/java/com/gindin/zmanim/android/location/acquirers/LatitudeLongitudeLocationAcquirer.java
+++ b/Android/src/main/java/com/gindin/zmanim/android/location/acquirers/LatitudeLongitudeLocationAcquirer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021. Jay R. Gindin
+ * Copyright (c) 2022. Jay R. Gindin
*/
package com.gindin.zmanim.android.location.acquirers;
@@ -68,7 +68,7 @@
}
try {
- ourLocation.atLatitude( LatitudeLongitudeParser.LATITUDE_PARSER.parseAsDouble( latitudePref ) );
+ ourLocation.atLatitude( LatitudeLongitudeParser.latitudeValue( latitudePref ) );
return null;
}
@@ -90,7 +90,7 @@
}
try {
- ourLocation.atLongitude( LatitudeLongitudeParser.LONGITUDE_PARSER.parseAsDouble( longitudePref ) );
+ ourLocation.atLongitude( LatitudeLongitudeParser.longitudeValue( longitudePref ) );
return null;
}
diff --git a/Android/src/main/java/com/gindin/zmanim/android/prefs/LongitudeLatitudePreference.java b/Android/src/main/java/com/gindin/zmanim/android/prefs/LongitudeLatitudePreference.java
--- a/Android/src/main/java/com/gindin/zmanim/android/prefs/LongitudeLatitudePreference.java
+++ b/Android/src/main/java/com/gindin/zmanim/android/prefs/LongitudeLatitudePreference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014. Jay R. Gindin
+ * Copyright (c) 2022. Jay R. Gindin
*/
package com.gindin.zmanim.android.prefs;
@@ -33,7 +33,7 @@
private View view;
private boolean showingLatitude;
- private LatitudeLongitudeParser.Holder valueHolder;
+ private LatitudeLongitudeParser valueHolder;
public LongitudeLatitudePreference(
@@ -51,10 +51,10 @@
this.showingLatitude = showingLatitude;
if ( showingLatitude ) {
- valueHolder = LatitudeLongitudeParser.LATITUDE_PARSER.parse( value );
+ valueHolder = LatitudeLongitudeParser.latitude( value );
}
else {
- valueHolder = LatitudeLongitudeParser.LONGITUDE_PARSER.parse( value );
+ valueHolder = LatitudeLongitudeParser.longitude( value );
}
}
@@ -84,16 +84,16 @@
ValueFilter minutesFilter = new ValueFilter( 0, 60 );
- EditText degrees = (EditText)view.findViewById( R.id.lat_long_editor_degrees_editor );
- degrees.setText( String.format( "%d", valueHolder.getDegrees() ) );
+ EditText degrees = view.findViewById( R.id.lat_long_editor_degrees_editor );
+ degrees.setText( String.format( "%d", valueHolder.degrees ) );
degrees.setFilters( new InputFilter[] { degreesFilter } );
- EditText minutes = (EditText)view.findViewById( R.id.lat_long_editor_minutes_editor );
- minutes.setText( String.format( "%d", valueHolder.getMinutes() ) );
+ EditText minutes = view.findViewById( R.id.lat_long_editor_minutes_editor );
+ minutes.setText( String.format( "%d", valueHolder.minutes ) );
minutes.setFilters( new InputFilter[] { minutesFilter } );
- TextView seconds = (TextView)view.findViewById( R.id.lat_long_editor_seconds_editor );
- seconds.setText( String.format( "%f", valueHolder.getSeconds() ) );
+ TextView seconds = view.findViewById( R.id.lat_long_editor_seconds_editor );
+ seconds.setText( String.format( "%f", valueHolder.seconds ) );
// Configuring the spinner comes straight from the Android JavaDocs:
@@ -112,13 +112,13 @@
ArrayAdapter adapter = ArrayAdapter.createFromResource( getContext(), arrayResource, android.R.layout.simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- Spinner spinner = (Spinner)view.findViewById( R.id.lat_long_editor_ns_ew_picker );
+ Spinner spinner = view.findViewById( R.id.lat_long_editor_ns_ew_picker );
spinner.setAdapter( adapter );
- TextView label = (TextView)view.findViewById( R.id.lat_long_editor_ns_text );
+ TextView label = view.findViewById( R.id.lat_long_editor_ns_text );
label.setText( labelText );
- LatitudeLongitudeParser.Direction direction = valueHolder.getDirection();
+ LatitudeLongitudeParser.Direction direction = valueHolder.direction;
if ( ( LatitudeLongitudeParser.Direction.NORTH == direction ) || ( LatitudeLongitudeParser.Direction.EAST == direction ) ) {
spinner.setSelection( 0, true );
}
@@ -137,27 +137,29 @@
}
// Have to convert the degrees, minutes, N/S (or E/W) to something we can store...
- TextView value = (TextView)view.findViewById( R.id.lat_long_editor_degrees_editor );
+ TextView value = view.findViewById( R.id.lat_long_editor_degrees_editor );
String degreesText = value.getText().toString();
- value = (TextView)view.findViewById( R.id.lat_long_editor_minutes_editor );
+ value = view.findViewById( R.id.lat_long_editor_minutes_editor );
String minutesText = value.getText().toString();
- value = (TextView)view.findViewById( R.id.lat_long_editor_seconds_editor );
+ value = view.findViewById( R.id.lat_long_editor_seconds_editor );
String secondsText = value.getText().toString();
LatitudeLongitudeParser.Direction direction;
- Spinner spinner = (Spinner)view.findViewById( R.id.lat_long_editor_ns_ew_picker );
+ Spinner spinner = view.findViewById( R.id.lat_long_editor_ns_ew_picker );
int item = spinner.getSelectedItemPosition();
+ LatitudeLongitudeParser holder;
if ( showingLatitude ) {
direction = ( 0 == item ? LatitudeLongitudeParser.Direction.NORTH : LatitudeLongitudeParser.Direction.SOUTH );
+ holder = LatitudeLongitudeParser.latitude( direction, degreesText, minutesText, secondsText );
}
else {
direction = ( 0 == item ? LatitudeLongitudeParser.Direction.EAST : LatitudeLongitudeParser.Direction.WEST );
+ holder = LatitudeLongitudeParser.longitude( direction, degreesText, minutesText, secondsText );
}
- LatitudeLongitudeParser.Holder holder = LatitudeLongitudeParser.parse( degreesText, minutesText, secondsText, direction );
String newValue = holder.toFullString( false );
if ( callChangeListener( newValue ) ) {
diff --git a/ZmanLib/src/main/java/com/gindin/zmanlib/location/LatitudeLongitudeParser.java b/ZmanLib/src/main/java/com/gindin/zmanlib/location/LatitudeLongitudeParser.java
--- a/ZmanLib/src/main/java/com/gindin/zmanlib/location/LatitudeLongitudeParser.java
+++ b/ZmanLib/src/main/java/com/gindin/zmanlib/location/LatitudeLongitudeParser.java
@@ -1,221 +1,205 @@
/*
- * Copyright (c) 2014. Jay R. Gindin
+ * Copyright (c) 2022. Jay R. Gindin
*/
package com.gindin.zmanlib.location;
+import com.gindin.util.Pair;
+
/**
* Used to parse a string into a latitude or a longitude.
- *
- *
+ *
+ *
* Supported formats are:
- *
- * - DDD MM['] [SS["]] -- Assumed North
- *
- [N|S] DDD MM['] [SS["]]
- *
- DDD.MM[N|S]
- *
+ *
+ * - DDD MM['] [SS["]] -- Assumed North
+ *
- [N|S] DDD MM['] [SS["]]
+ *
- DDD.MM[N|S]
+ *
*/
-public abstract class LatitudeLongitudeParser {
+public class LatitudeLongitudeParser {
+
+ private static final int MAX_LATITUDE = 90;
- public static enum Direction {
+ private static final int MAX_LONGITUDE = 180;
+
+ public enum Direction {
NORTH( "N" ),
SOUTH( "S" ),
EAST( "E" ),
WEST( "W" );
- private final String abbreviation;
+ private final String abbreviation;
+
Direction( String abbreviation ) {
this.abbreviation = abbreviation;
}
}
- public static class Holder {
+ private static final int MINUTES_PER_DEGREE = 60;
+ private static final int SECONDS_PER_MINUTE = 60;
- private Direction direction;
- private int minutes;
- private int degrees;
- private double seconds = 0;
-
-
- public Holder() {
- this( Direction.NORTH, 0, 0, 0 );
- }
+ public final Direction direction;
+ public final int minutes;
+ public final int degrees;
+ public final double seconds;
- public Holder(
- Direction direction,
- int degrees,
- int minutes,
- double seconds
- ) {
- setDirection( direction );
- setDegrees( degrees );
- setMinutes( minutes );
- setSeconds( seconds );
+ @SuppressWarnings( "AssignmentToMethodParameter" )
+ protected LatitudeLongitudeParser(
+ Direction direction,
+ int degrees,
+ int minutes,
+ double seconds,
+ int maxDegrees
+ ) {
+
+ if ( degrees < 0 ) {
+ if ( Direction.NORTH == direction ) {
+ direction = Direction.SOUTH;
+ }
+ else if ( Direction.EAST == direction ) {
+ direction = Direction.WEST;
+ }
+
+ degrees = degrees * -1;
}
+ this.direction = direction;
+ this.minutes = minutes;
+ this.seconds = seconds;
+
+ // If the value is still too large, then just choose zero.
+ if ( degrees > maxDegrees ) {
+ this.degrees = 0;
+ }
+ else {
+ this.degrees = degrees;
+ }
+ }
+
- public Direction getDirection() {
- return direction;
+ public String toFullString( boolean withMarkers ) {
+ return direction.abbreviation + " " + formattedDMS( withMarkers );
+ }
+
+
+ public String toSimpleString( boolean withMarkers ) {
+ String str;
+ if ( ( Direction.SOUTH == direction ) || ( Direction.WEST == direction ) ) {
+ str = direction.abbreviation + " ";
}
-
- void setDirection( Direction direction ) {
- this.direction = direction;
+ else {
+ str = "";
}
- void updateDirection() {
+ return str + formattedDMS( withMarkers );
+ }
+
+
+ private String formattedDMS( boolean withMarkers ) {
- if ( getDegrees() < 1 ) {
- if ( Direction.NORTH == getDirection() ) {
- setDirection( Direction.SOUTH );
- }
- else if ( Direction.EAST == getDirection() ) {
- setDirection( Direction.WEST );
- }
+ StringBuilder str = new StringBuilder().append( degrees );
+ if ( ( 0 != minutes ) || ( 0 != seconds ) ) {
+ str.append( " " ).append( minutes );
+ if ( withMarkers ) {
+ str.append( "'" );
+ }
+ }
- setDegrees( getDegrees() * -1 );
+ if ( 0 != seconds ) {
+ str.append( " " ).append( seconds );
+ if ( withMarkers ) {
+ str.append( "\"" );
}
}
-
- public int getDegrees() {
- return degrees;
- }
-
- void setDegrees( int degrees ) {
- this.degrees = degrees;
- }
-
-
- public int getMinutes() {
- return minutes;
- }
-
- void setMinutes( int minutes ) {
- this.minutes = minutes;
- }
-
+ return str.toString();
+ }
- public double getSeconds() {
- return seconds;
- }
-
- void setSeconds( double seconds ) {
- this.seconds = seconds;
- }
-
-
- public String toFullString( boolean withMarkers ) {
- return direction.abbreviation + " " + formattedDMS( withMarkers );
- }
-
-
- public String toSimpleString( boolean withMarkers ) {
- String str;
- if ( ( Direction.SOUTH == direction ) || ( Direction.WEST == direction ) ) {
- str = direction.abbreviation + " ";
- }
- else {
- str = "";
- }
-
- return str + formattedDMS( withMarkers );
- }
+ static public LatitudeLongitudeParser latitude(
+ Direction direction,
+ int degrees,
+ int minutes,
+ int seconds
+ ) {
+ return new LatitudeLongitudeParser( direction, degrees, minutes, seconds, MAX_LATITUDE );
+ }
- private String formattedDMS( boolean withMarkers ) {
-
- StringBuilder str = new StringBuilder().append( degrees );
- if ( ( 0 != minutes ) || ( 0 != seconds ) ) {
- str.append( " " ).append( minutes );
- if ( withMarkers ) {
- str.append( "'" );
- }
- }
-
- if ( 0 != seconds ) {
- str.append( " " ).append( seconds );
- if ( withMarkers ) {
- str.append( "\"" );
- }
- }
-
- return str.toString();
- }
+ static public LatitudeLongitudeParser latitude(
+ Direction direction,
+ String degreesText,
+ String minutesText,
+ String secondsText
+ ) {
+ return parse( direction, degreesText, minutesText, secondsText, MAX_LATITUDE );
}
- public static final LatitudeLongitudeParser LATITUDE_PARSER = new LatitudeParser();
- public static final LatitudeLongitudeParser LONGITUDE_PARSER = new LongitudeParser();
-
- protected abstract double getMax();
+ static public LatitudeLongitudeParser latitude( String value ) {
+ return parse( value, Direction.NORTH, MAX_LATITUDE );
+ }
- @SuppressWarnings( "AssignmentToMethodParameter" )
- public Holder parse( String value ) {
-
- Holder holder = new Holder();
-
- // Make sure there's no extra whitespace...
- value = value.trim();
+ static public double latitudeValue( String value ) {
+
+ double latitude = parseAsDouble( value, Direction.NORTH, MAX_LATITUDE );
- // NOTE: I used to try to parse the value directly into a double. I don't think this really makes sense, though,
- // and quite possibly explains why so many users got confused and couldn't make this functionality work the
- // way they thought it should.
-// try {
-// return Double.parseDouble( value );
-// }
-// catch ( NumberFormatException e ) {
-// // Well, keep trying to parse.
-// }
-//
- value = extractDirection( value, holder );
-
- // Clean up the input....
- value = value.replace( '.', ' ' );
- value = value.replace( '\'', ' ' );
- value = value.replace( '\"', ' ' );
- value = value.trim();
-
-
- String[] latitudeComponents = value.split( " " );
- if ( 0 == latitudeComponents.length ) {
- throw new IllegalArgumentException( "Can't parse value: " + value );
+ // Latitude must be -90 <= lat <= 90
+ if ( ( latitude < -MAX_LATITUDE ) || ( latitude > MAX_LATITUDE ) ) {
+ latitude = 0;
}
- holder.setDegrees( Integer.parseInt( latitudeComponents[ 0 ].trim() ) );
- holder.updateDirection();
-
- if ( latitudeComponents.length > 1 ) {
- holder.setMinutes( Integer.parseInt( latitudeComponents[ 1 ].trim() ) );
- }
-
- if ( latitudeComponents.length > 2 ) {
- holder.setSeconds( Integer.parseInt( latitudeComponents[ 2 ].trim() ) );
- }
-
- // Ahhh, but wait. IFF the value is too large, then perhaps what the user was entering was, after all, in
- // decimal format?
- // NOTE: Removed this for the same reason as why I removed the blanket parsing into a double...
-// if ( holder.getDegrees() > getMax() && ( holder.getMinutes() > 0 ) ) {
-// holder.setDegrees( Double.parseDouble( latitudeComponents[0] + "." + latitudeComponents[1] ) );
-// }
-
- // If the value is still too large, then just choose zero.
- if ( holder.getDegrees() > getMax() ) {
- holder.setDegrees( 0 );
- }
-
- return holder;
+ return latitude;
}
- public static Holder parse(
- String degreesText,
- String minutesText,
- String secondsText,
- LatitudeLongitudeParser.Direction direction
+ static public LatitudeLongitudeParser longitude(
+ Direction direction,
+ int degrees,
+ int minutes,
+ int seconds
+ ) {
+ return new LatitudeLongitudeParser( direction, degrees, minutes, seconds, MAX_LONGITUDE );
+ }
+
+
+ static public LatitudeLongitudeParser longitude(
+ Direction direction,
+ String degreesText,
+ String minutesText,
+ String secondsText
+ ) {
+ return parse( direction, degreesText, minutesText, secondsText, MAX_LONGITUDE );
+ }
+
+
+ static public LatitudeLongitudeParser longitude( String value ) {
+ return parse( value, Direction.EAST, MAX_LONGITUDE );
+ }
+
+
+ static public double longitudeValue( String value ) {
+
+ double longitude = parseAsDouble( value, Direction.EAST, MAX_LONGITUDE );
+
+ // Longitude must be -180 <= long <= 180
+ if ( ( longitude < -MAX_LONGITUDE ) || ( longitude > MAX_LONGITUDE ) ) {
+ longitude = MAX_LONGITUDE;
+ }
+
+ return longitude;
+ }
+
+
+ private static LatitudeLongitudeParser parse(
+ Direction direction,
+ String degreesText,
+ String minutesText,
+ String secondsText,
+ int maxDegrees
) {
boolean parseMinutes = true;
@@ -223,7 +207,7 @@
int degrees;
int minutes = 0;
double seconds = 0;
-
+
try {
degrees = Integer.parseInt( degreesText );
}
@@ -236,10 +220,10 @@
degrees = (int)degreesDouble;
// Now, convert the decimal portion to the minutes. http://geography.about.com/library/howto/htdegrees.htm
- double doubleMinutes = Math.abs( ( ( degreesDouble - degrees ) * 60 ) );
+ double doubleMinutes = Math.abs( ( ( degreesDouble - degrees ) * MINUTES_PER_DEGREE ) );
minutes = (int)doubleMinutes;
- seconds = ( ( doubleMinutes - minutes ) * 60 );
+ seconds = ( ( doubleMinutes - minutes ) * SECONDS_PER_MINUTE );
parseMinutes = false;
}
@@ -260,7 +244,6 @@
minutes = 0;
}
-
try {
seconds = Double.parseDouble( secondsText );
}
@@ -268,28 +251,27 @@
seconds = 0;
}
}
-
- final Holder holder = new Holder( direction, degrees, minutes, seconds );
- holder.updateDirection();
-
- return holder;
+
+ return new LatitudeLongitudeParser( direction, degrees, minutes, seconds, maxDegrees );
}
/**
* Attempts to parse the specified string representing a latitude or longitude into a double containing the
- * decimal representation.
+ * decimal representation.
*/
- public double parseAsDouble( String value )
- throws IllegalArgumentException {
+ private static double parseAsDouble(
+ String value,
+ Direction defaultDirection,
+ int maxDegress
+ ) {
- Holder holder = parse( value );
+ final LatitudeLongitudeParser parsed = parse( value, defaultDirection, maxDegress );
- // See http://stackoverflow.com/questions/6945008/converting-value-longitude-valuesdmscompass-direction-format-to-correspondi
- //noinspection MagicNumber
- double convertedDegrees = holder.getDegrees() + ( ( ( (double)holder.getSeconds() / 60 ) ) + holder.getMinutes() ) / (double)60;
+ // See http://stackoverflow.com/questions/6945008/converting-value-longitude-valuesdmscompass-direction-format-to-correspondi
+ double convertedDegrees = parsed.degrees + ( ( ( parsed.seconds / SECONDS_PER_MINUTE ) ) + parsed.minutes ) / (double)MINUTES_PER_DEGREE;
- if ( ( Direction.SOUTH == holder.getDirection() ) || ( Direction.WEST == holder.getDirection() ) ) {
+ if ( ( Direction.SOUTH == parsed.direction ) || ( Direction.WEST == parsed.direction ) ) {
convertedDegrees = -1 * convertedDegrees;
}
@@ -298,96 +280,103 @@
@SuppressWarnings( "AssignmentToMethodParameter" )
- private String extractDirection(
- String value,
- Holder holder
+ private static LatitudeLongitudeParser parse(
+ String value,
+ Direction defaultDirection,
+ int maxDegrees
+ ) {
+
+ // Make sure there's no extra whitespace...
+ value = value.trim();
+
+ // NOTE: I used to try to parse the value directly into a double. I don't think this really makes sense, though,
+ // and quite possibly explains why so many users got confused and couldn't make this functionality work the
+ // way they thought it should.
+// try {
+// return Double.parseDouble( value );
+// }
+// catch ( NumberFormatException e ) {
+// // Well, keep trying to parse.
+// }
+//
+ final Pair extracted = extractDirection( value, defaultDirection );
+ value = extracted.second;
+
+ // Clean up the input....
+ value = value.replace( '.', ' ' );
+ value = value.replace( '\'', ' ' );
+ value = value.replace( '\"', ' ' );
+ value = value.trim();
+
+
+ String[] latitudeComponents = value.split( " " );
+ if ( 0 == latitudeComponents.length ) {
+ throw new IllegalArgumentException( "Can't parse value: " + value );
+ }
+
+ int degrees = Integer.parseInt( latitudeComponents[ 0 ].trim() );
+
+ int minutes;
+ if ( latitudeComponents.length > 1 ) {
+ minutes = Integer.parseInt( latitudeComponents[ 1 ].trim() );
+ }
+ else {
+ minutes = 0;
+ }
+
+ int seconds;
+ if ( latitudeComponents.length > 2 ) {
+ seconds = Integer.parseInt( latitudeComponents[ 2 ].trim() );
+ }
+ else {
+ seconds = 0;
+ }
+
+ // Ahhh, but wait. IFF the value is too large, then perhaps what the user was entering was, after all, in
+ // decimal format?
+ // NOTE: Removed this for the same reason as why I removed the blanket parsing into a double...
+// if ( holder.getDegrees() > getMax() && ( holder.getMinutes() > 0 ) ) {
+// holder.setDegrees( Double.parseDouble( latitudeComponents[0] + "." + latitudeComponents[1] ) );
+// }
+
+ return new LatitudeLongitudeParser( extracted.first, degrees, minutes, seconds, maxDegrees );
+ }
+
+
+ private static Pair extractDirection(
+ String value,
+ Direction defaultDirection
) {
char test = value.charAt( 0 );
if ( ( 'S' == test ) || ( 's' == test ) ) {
- value = value.substring( 1 );
- holder.setDirection( Direction.SOUTH );
+ return new Pair<>( Direction.SOUTH, value.substring( 1 ) );
}
else if ( ( 'W' == test ) || ( 'w' == test ) ) {
- value = value.substring( 1 );
- holder.setDirection( Direction.WEST );
+ return new Pair<>( Direction.WEST, value.substring( 1 ) );
}
else if ( ( 'N' == test ) || ( 'n' == test ) ) {
- value = value.substring( 1 );
- holder.setDirection( Direction.NORTH );
+ return new Pair<>( Direction.NORTH, value.substring( 1 ) );
}
else if ( ( 'E' == test ) || ( 'e' == test ) ) {
- value = value.substring( 1 );
- holder.setDirection( Direction.EAST );
+ return new Pair<>( Direction.EAST, value.substring( 1 ) );
}
test = value.charAt( value.length() - 1 );
if ( ( 'S' == test ) || ( 's' == test ) ) {
- value = value.substring( 0, value.length() - 1 );
- holder.setDirection( Direction.SOUTH );
+ return new Pair<>( Direction.SOUTH, value.substring( 0, value.length() - 1 ) );
}
else if ( ( 'W' == test ) || ( 'w' == test ) ) {
- value = value.substring( 0, value.length() - 1 );
- holder.setDirection( Direction.WEST );
+ return new Pair<>( Direction.WEST, value.substring( 0, value.length() - 1 ) );
}
else if ( ( 'N' == test ) || ( 'n' == test ) ) {
- value = value.substring( 0, value.length() - 1 );
- holder.setDirection( Direction.NORTH );
+ return new Pair<>( Direction.NORTH, value.substring( 0, value.length() - 1 ) );
}
else if ( ( 'E' == test ) || ( 'e' == test ) ) {
- value = value.substring( 0, value.length() - 1 );
- holder.setDirection( Direction.EAST );
- }
-
- return value.trim();
- }
-
-
- static class LatitudeParser
- extends LatitudeLongitudeParser {
-
- @Override
- protected double getMax() {
- //noinspection MagicNumber
- return 90;
+ return new Pair<>( Direction.EAST, value.substring( 0, value.length() - 1 ) );
}
-
- @Override
- public double parseAsDouble( String value ) throws IllegalArgumentException {
- double parsed = super.parseAsDouble( value );
-
- // Latitude must be -90 <= lat <= 90
- if ( ( parsed < -90 ) || ( parsed > 90 ) ) {
- parsed = 0;
- }
-
- return parsed;
- }
+ return new Pair<>( defaultDirection, value );
}
-
-
- static class LongitudeParser
- extends LatitudeLongitudeParser {
-
- @Override
- protected double getMax() {
- //noinspection MagicNumber
- return 180;
- }
-
-
- @Override
- public double parseAsDouble( String value ) throws IllegalArgumentException {
- double parsed = super.parseAsDouble( value );
-
- // Longitude must be -180 <= long <= 180
- if ( ( parsed < -180 ) || ( parsed > 180 ) ) {
- parsed = 180;
- }
-
- return parsed;
- }
- }
}
diff --git a/ZmanLib/src/test/java/com/gindin/zmanlib/location/UT_LatitudeLongitudeParser.java b/ZmanLib/src/test/java/com/gindin/zmanlib/location/UT_LatitudeLongitudeParser.java
--- a/ZmanLib/src/test/java/com/gindin/zmanlib/location/UT_LatitudeLongitudeParser.java
+++ b/ZmanLib/src/test/java/com/gindin/zmanlib/location/UT_LatitudeLongitudeParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014. Jay R. Gindin
+ * Copyright (c) 2022. Jay R. Gindin
*/
package com.gindin.zmanlib.location;
@@ -16,13 +16,12 @@
/**
* Test our ability to properly parse latitude & longitude.
- *
- *
+ *
+ *
* City data comes from: http://www.infoplease.com/ipa/A0001769.html, http://www.infoplease.com/ipa/A0001796.html
- *
- *
+ *
+ *
* A good converter seems to be: http://www.csgnetwork.com/gpscoordconv.html
- *
*/
@SuppressWarnings( "MagicNumber" )
@RunWith( Parameterized.class )
@@ -30,19 +29,23 @@
private static class CityInfo {
- final String cityName;
- final LatitudeLongitudeParser.Holder latitude;
- final LatitudeLongitudeParser.Holder longitude;
- final double convertedLatitude;
- final double convertedLongitude;
+ final String cityName;
+
+ final LatitudeLongitudeParser latitude;
+
+ final LatitudeLongitudeParser longitude;
+
+ final double convertedLatitude;
+
+ final double convertedLongitude;
private CityInfo(
- String cityName,
- LatitudeLongitudeParser.Holder latitude,
- LatitudeLongitudeParser.Holder longitude,
- double convertedLatitude,
- double convertedLongitude
+ String cityName,
+ LatitudeLongitudeParser latitude,
+ LatitudeLongitudeParser longitude,
+ double convertedLatitude,
+ double convertedLongitude
) {
this.cityName = cityName;
this.latitude = latitude;
@@ -59,96 +62,82 @@
}
- /** Info for the city we're currently testing. */
- private final CityInfo cityInfoToTest;
+ /**
+ * Info for the city we're currently testing.
+ */
+ private final CityInfo cityInfoToTest;
+
@Parameterized.Parameters( name = "{0}" )
- public static Collection gatherTestData() {
+ public static Collection gatherTestData() {
- CityInfo[][] cityInfos = new CityInfo[][] {
+ return Arrays.asList(
- {
- new CityInfo(
- "Aberdeen, Scotland",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.NORTH, 57, 9, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.WEST, 2, 9, 0 ),
- 57.15,
- -2.15
- )
- },
+ new CityInfo(
+ "Aberdeen, Scotland",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.NORTH, 57, 9, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.WEST, 2, 9, 0 ),
+ 57.15,
+ -2.15
+ ),
- {
- new CityInfo(
- "Adelaide, Australia",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.SOUTH, 34, 55, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.EAST, 138, 36, 0 ),
- -34.91666666666666666667,
- 138.6
- )
- },
+ new CityInfo(
+ "Adelaide, Australia",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.SOUTH, 34, 55, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.EAST, 138, 36, 0 ),
+ -34.91666666666666666667,
+ 138.6
+ ),
- {
- new CityInfo(
- "Tel Aviv",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.NORTH, 32, 4, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.EAST, 34, 46, 0 ),
- 32.06666666666666666667,
- 34.76666666666666666667
- )
- },
+ new CityInfo(
+ "Tel Aviv",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.NORTH, 32, 4, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.EAST, 34, 46, 0 ),
+ 32.06666666666666666667,
+ 34.76666666666666666667
+ ),
- {
- new CityInfo(
- "Seattle, WA",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.NORTH, 47, 37, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.WEST, 122, 20, 0 ),
- 47.61666666666666666667,
- -122.33333333333333333333
- )
- },
+ new CityInfo(
+ "Seattle, WA",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.NORTH, 47, 37, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.WEST, 122, 20, 0 ),
+ 47.61666666666666666667,
+ -122.33333333333333333333
+ ),
- {
- new CityInfo(
- "New York, NY",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.NORTH, 40, 47, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.WEST, 73, 58, 0 ),
- 40.78333333333333333333,
- -73.96666666666666666667
- )
- },
+ new CityInfo(
+ "New York, NY",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.NORTH, 40, 47, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.WEST, 73, 58, 0 ),
+ 40.78333333333333333333,
+ -73.96666666666666666667
+ ),
- {
- new CityInfo(
- "San Francisco, Calif.",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.NORTH, 37, 47, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.WEST, 122, 26, 0 ),
- 37.78333333333333333333,
- -122.43333333333333333333
- )
- },
+ new CityInfo(
+ "San Francisco, Calif.",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.NORTH, 37, 47, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.WEST, 122, 26, 0 ),
+ 37.78333333333333333333,
+ -122.43333333333333333333
+ ),
- {
- new CityInfo(
- "Phoenix, Ariz.",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.NORTH, 33, 29, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.WEST, 112, 4, 0 ),
- 33.48333333333333333333,
- -112.06666666666666666667
- )
- },
+ new CityInfo(
+ "Phoenix, Ariz.",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.NORTH, 33, 29, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.WEST, 112, 4, 0 ),
+ 33.48333333333333333333,
+ -112.06666666666666666667
+ ),
- {
- new CityInfo(
- "Ottawa, Ont., Can.",
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.NORTH, 45, 24, 0 ),
- new LatitudeLongitudeParser.Holder( LatitudeLongitudeParser.Direction.WEST, 73, 43, 0 ),
- 45.4,
- -73.71666666666666666667
- )
- }
- };
+ new CityInfo(
+ "Ottawa, Ont., Can.",
+ LatitudeLongitudeParser.latitude( LatitudeLongitudeParser.Direction.NORTH, 45, 24, 0 ),
+ LatitudeLongitudeParser.longitude( LatitudeLongitudeParser.Direction.WEST, 73, 43, 0 ),
+ 45.4,
+ -73.71666666666666666667
+ )
+ );
- return Arrays.asList( cityInfos );
}
@@ -162,6 +151,7 @@
fullString( false );
}
+
@Test
public void testFullStringParsingWithMarkers() {
fullString( true );
@@ -173,6 +163,7 @@
simpleString( false );
}
+
@Test
public void testSimpleStringParsingWithMarkers() {
simpleString( true );
@@ -182,60 +173,74 @@
@Test
public void fullDecimalInDegrees() {
- final LatitudeLongitudeParser.Holder latitude = cityInfoToTest.latitude;
- LatitudeLongitudeParser.Holder holder = LatitudeLongitudeParser.parse(
- Double.toString( cityInfoToTest.convertedLatitude ), "", "", latitude.getDirection() );
- Assert.assertEquals( cityInfoToTest.cityName + " latitude.getDegrees()", latitude.getDegrees(), holder.getDegrees() );
+ final LatitudeLongitudeParser latitude = cityInfoToTest.latitude;
+ LatitudeLongitudeParser holder = LatitudeLongitudeParser.latitude( latitude.direction,
+ Double.toString( cityInfoToTest.convertedLatitude ), "", "" );
+ Assert.assertEquals( cityInfoToTest.cityName + " latitude.degrees", latitude.degrees,
+ holder.degrees );
// This gets a bit complicated because IF the actual is ONE degree larger AND we have seconds, THEN that has
// happened because of rounding...
- Assert.assertThat( cityInfoToTest.cityName + " latitude.getMinutes()", latitude, new DegreesWithRoundingMatcher( holder ) );
+ Assert.assertThat( cityInfoToTest.cityName + " latitude.getMinutes()", latitude,
+ new DegreesWithRoundingMatcher( holder ) );
- if ( latitude.getSeconds() != 0 ) {
- Assert.assertEquals( cityInfoToTest.cityName + " latitude.getSeconds()", latitude.getSeconds(), holder.getSeconds(), 0 );
+ if ( latitude.seconds != 0 ) {
+ Assert.assertEquals( cityInfoToTest.cityName + " latitude.seconds", latitude.seconds,
+ holder.seconds, 0 );
}
- final LatitudeLongitudeParser.Holder longitude = cityInfoToTest.longitude;
- holder = LatitudeLongitudeParser.parse(
- Double.toString( cityInfoToTest.convertedLongitude ), "", "", longitude.getDirection() );
- Assert.assertEquals( cityInfoToTest.cityName + " longitude.getDegrees()", longitude.getDegrees(), holder.getDegrees() );
- Assert.assertThat( cityInfoToTest.cityName + " longitude.getMinutes()", longitude, new DegreesWithRoundingMatcher( holder ) );
+ final LatitudeLongitudeParser longitude = cityInfoToTest.longitude;
+ holder = LatitudeLongitudeParser.longitude( longitude.direction,
+ Double.toString( cityInfoToTest.convertedLongitude ), "", "" );
+ Assert.assertEquals( cityInfoToTest.cityName + " longitude.degrees", longitude.degrees,
+ holder.degrees );
+ Assert.assertThat( cityInfoToTest.cityName + " longitude.getMinutes()", longitude,
+ new DegreesWithRoundingMatcher( holder ) );
- if ( longitude.getSeconds() != 0 ) {
- Assert.assertEquals( cityInfoToTest.cityName + " longitude.getSeconds()", longitude.getSeconds(), holder.getSeconds(), 0 );
+ if ( longitude.seconds != 0 ) {
+ Assert.assertEquals( cityInfoToTest.cityName + " longitude.seconds", longitude.seconds,
+ holder.seconds, 0 );
}
}
private void fullString( boolean withMarkers ) {
- double converted = LatitudeLongitudeParser.LATITUDE_PARSER.parseAsDouble( cityInfoToTest.latitude.toFullString( withMarkers ) );
- Assert.assertEquals( cityInfoToTest.cityName + " latitude", cityInfoToTest.convertedLatitude, converted, 0.1 );
+ double converted = LatitudeLongitudeParser.latitudeValue(
+ cityInfoToTest.latitude.toFullString( withMarkers ) );
+ Assert.assertEquals( cityInfoToTest.cityName + " latitude", cityInfoToTest.convertedLatitude,
+ converted, 0.1 );
- converted = LatitudeLongitudeParser.LONGITUDE_PARSER.parseAsDouble( cityInfoToTest.longitude.toFullString( withMarkers ) );
- Assert.assertEquals( cityInfoToTest.cityName + " longitude", cityInfoToTest.convertedLongitude, converted, 0.1 );
+ converted = LatitudeLongitudeParser.longitudeValue(
+ cityInfoToTest.longitude.toFullString( withMarkers ) );
+ Assert.assertEquals( cityInfoToTest.cityName + " longitude", cityInfoToTest.convertedLongitude,
+ converted, 0.1 );
}
private void simpleString( boolean withMarkers ) {
- double converted = LatitudeLongitudeParser.LATITUDE_PARSER.parseAsDouble( cityInfoToTest.latitude.toSimpleString( withMarkers ) );
- Assert.assertEquals( cityInfoToTest.cityName + " latitude", cityInfoToTest.convertedLatitude, converted, 0.1 );
+ double converted = LatitudeLongitudeParser.latitudeValue(
+ cityInfoToTest.latitude.toSimpleString( withMarkers ) );
+ Assert.assertEquals( cityInfoToTest.cityName + " latitude", cityInfoToTest.convertedLatitude,
+ converted, 0.1 );
- converted = LatitudeLongitudeParser.LONGITUDE_PARSER.parseAsDouble( cityInfoToTest.longitude.toSimpleString( withMarkers ) );
- Assert.assertEquals( cityInfoToTest.cityName + " longitude", cityInfoToTest.convertedLongitude, converted, 0.1 );
+ converted = LatitudeLongitudeParser.longitudeValue(
+ cityInfoToTest.longitude.toSimpleString( withMarkers ) );
+ Assert.assertEquals( cityInfoToTest.cityName + " longitude", cityInfoToTest.convertedLongitude,
+ converted, 0.1 );
}
+ private static class DegreesWithRoundingMatcher
+ extends BaseMatcher {
+
+ private final LatitudeLongitudeParser actual;
+
+ private String mismatchReason;
- private static class DegreesWithRoundingMatcher
- extends BaseMatcher {
-
- private final LatitudeLongitudeParser.Holder actual;
- private String mismatchReason;
-
- DegreesWithRoundingMatcher(LatitudeLongitudeParser.Holder actual) {
+ DegreesWithRoundingMatcher( LatitudeLongitudeParser actual ) {
this.actual = actual;
}
@@ -243,25 +248,26 @@
@Override
public boolean matches( Object item ) {
- LatitudeLongitudeParser.Holder expected = (LatitudeLongitudeParser.Holder)item;
+ LatitudeLongitudeParser expected = (LatitudeLongitudeParser)item;
- int diff = expected.getMinutes() - actual.getMinutes();
+ int diff = expected.minutes - actual.minutes;
if ( diff == 0 ) {
return true;
}
if ( diff == 1 ) {
- if ( ( expected.getSeconds() == 0 ) && ( actual.getSeconds() > 0 ) ) {
+ if ( ( expected.seconds == 0 ) && ( actual.seconds > 0 ) ) {
return true;
}
}
- mismatchReason = "diff " + diff + " and expected seconds: " + expected.getSeconds() +
- " but actual seconds: " + actual.getSeconds();
+ mismatchReason = "diff " + diff + " and expected seconds: " + expected.seconds +
+ " but actual seconds: " + actual.seconds;
return false;
}
+
@Override
public void describeTo( Description description ) {