Skip to content

Commit

Permalink
Merge pull request #36 from observerly/feature/humanize/FormatDecimal…
Browse files Browse the repository at this point in the history
…ToDMS

feat: add FormatDecimalToDMS to humanize module in @observerly/sidera
  • Loading branch information
michealroberts authored Jan 21, 2025
2 parents ecca066 + e0e858d commit b8a54d1
Show file tree
Hide file tree
Showing 2 changed files with 235 additions and 0 deletions.
38 changes: 38 additions & 0 deletions pkg/humanize/humanize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*****************************************************************************************************************/

// @author Michael Roberts <michael@observerly.com>
// @package @observerly/sidera
// @license Copyright © 2021-2024 observerly

/*****************************************************************************************************************/

package humanize

import (
"fmt"
"math"

"github.com/observerly/sidera/pkg/common"
)

/*****************************************************************************************************************/

// DecimalToDMS converts a decimal degree to degrees, minutes, and seconds.
// Returns a formatted string e.g., for "123°27'40.48\"", use "%s%d°%d'%0.2f\"".
func FormatDecimalToDMS(value float64, format string) string {
// Determine the sign, starting with a positive sign:
sign := "+"

// If the degrees are negative, change the sign and make the degrees positive:
if value < 0 {
sign = "-"
value = math.Abs(value)
}

_, degrees, minutes, seconds := common.DegreesToHDMS(value)

// Return the formatted string:
return fmt.Sprintf(format, sign, degrees, minutes, seconds)
}

/*****************************************************************************************************************/
197 changes: 197 additions & 0 deletions pkg/humanize/humanize_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*****************************************************************************************************************/

// @author Michael Roberts <michael@observerly.com>
// @package @observerly/sidera
// @license Copyright © 2021-2024 observerly

/*****************************************************************************************************************/

package humanize

import (
"testing"
)

/*****************************************************************************************************************/

// TestFormatDecimalToDMSPositiveDegreesWithFractionalPart tests positive degrees with a fractional part.
func TestFormatDecimalToDMSPositiveDegreesWithFractionalPart(t *testing.T) {
value := 123.461
format := "%s%d°%d'%0.2f\""
expected := "+123°27'39.60\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSNegativeDegreesWithFractionalPart tests negative degrees with a fractional part.
func TestFormatDecimalToDMSNegativeDegreesWithFractionalPart(t *testing.T) {
value := -45.75
format := "%s%d°%d'%0.2f\""
expected := "-45°45'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSZeroDegrees tests zero degrees.
func TestFormatDecimalToDMSZeroDegrees(t *testing.T) {
value := 0.0
format := "%s%d°%d'%0.2f\""
expected := "+0°0'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSExtactDegreeWithoutFractionalPart tests exact degrees without a fractional part.
func TestFormatDecimalToDMSExtactDegreeWithoutFractionalPart(t *testing.T) {
value := 90.0
format := "%s%d°%d'%0.2f\""
expected := "+90°0'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSEdgeCaseJustBelowIntegerDegree tests an edge case just below an integer degree.
func TestFormatDecimalToDMSEdgeCaseJustBelowIntegerDegree(t *testing.T) {
value := 30.999999
format := "%s%d°%d'%0.4f\""
expected := "+30°59'59.9964\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSEdgeCaseJustAboveIntegerDegree tests an edge case just above an integer degree.
func TestFormatDecimalToDMSEdgeCaseJustAboveIntegerDegree(t *testing.T) {
value := 30.000001
format := "%s%d°%d'%0.2f\""
expected := "+30°0'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSNegativeEdgeCaseJustBelowZero tests a negative edge case just below zero.
func TestFormatDecimalToDMSNegativeEdgeCaseJustBelowZero(t *testing.T) {
value := -0.000001
format := "%s%d°%d'%0.2f\""
expected := "-0°0'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSHalfDegree tests a half degree value.
func TestFormatDecimalToDMSHalfDegree(t *testing.T) {
value := 180.5
format := "%s%d°%d'%0.2f\""
expected := "+180°30'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSNegativeDegreesWithMultipleDecimalPlaces tests negative degrees with multiple decimal places.
func TestFormatDecimalToDMSNegativeDegreesWithMultipleDecimalPlaces(t *testing.T) {
value := -123.456789
format := "%s%d°%d'%0.2f\""
expected := "-123°27'24.44\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSDifferentFormatString tests a different format string.
func TestFormatDecimalToDMSDifferentFormatString(t *testing.T) {
value := 45.1234
format := "%s%d deg %d min %0.2f sec"
expected := "+45 deg 7 min 24.24 sec"

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSLargePositiveValue tests a large positive degree value.
func TestFormatDecimalToDMSLargePositiveValue(t *testing.T) {
value := 360.0
format := "%s%d°%d'%0.2f\""
expected := "+360°0'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSLargeNegativeValue tests a large negative degree value.
func TestFormatDecimalToDMSLargeNegativeValue(t *testing.T) {
value := -360.0
format := "%s%d°%d'%0.2f\""
expected := "-360°0'0.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

// TestFormatDecimalToDMSVerySmallFractionalDegree tests a very small fractional degree.
func TestFormatDecimalToDMSVerySmallFractionalDegree(t *testing.T) {
value := 0.000277778 // Approximately 1 second
format := "%s%d°%d'%0.2f\""
expected := "+0°0'1.00\""

result := FormatDecimalToDMS(value, format)
if result != expected {
t.Errorf("FormatDecimalToDMS(%f, %q) = %q; want %q", value, format, result, expected)
}
}

/*****************************************************************************************************************/

0 comments on commit b8a54d1

Please sign in to comment.