From b8d9503ad950bf33cd45f1fde7e0fe9f9ba37704 Mon Sep 17 00:00:00 2001 From: Ajesh Sen Thapa Date: Sun, 19 Feb 2023 20:36:40 +0545 Subject: [PATCH] Refactored dateConverter code with one single reference point #8 --- dateConverter/converter.go | 127 ++++++++++++++++++++++---------- dateConverter/converter_test.go | 24 ++++++ 2 files changed, 111 insertions(+), 40 deletions(-) diff --git a/dateConverter/converter.go b/dateConverter/converter.go index 3cd8b6d..36ff11c 100644 --- a/dateConverter/converter.go +++ b/dateConverter/converter.go @@ -1,5 +1,4 @@ // This package contains the date converter functions. -// Reference date for conversion is 2000/01/01 BS and 1943/4/14 AD // // USAGE: // y, m, d := EnglishToNepali(2023, 1, 15) @@ -11,6 +10,10 @@ import ( "math" ) +// Reference date for conversion is 2000/01/01 BS and 1943/4/14 AD +var npInitialYear int16 = 2000 +var referenceEnDate = [3]int16{1943, 4, 14} + type NepaliMonthData struct { monthData [12]int8 yearDays int16 @@ -20,7 +23,7 @@ var enMonths = [12]int8{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} var enLeapMonths = [12]int8{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} var npMonthData = [100]NepaliMonthData{ - {[12]int8{30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31}, 365}, // 2000 BS - 1944 AD + {[12]int8{30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31}, 365}, // 2000 BS - 1943/1944 AD {[12]int8{31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30}, 365}, // 2001 BS {[12]int8{31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30}, 365}, {[12]int8{31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31}, 366}, @@ -122,11 +125,63 @@ var npMonthData = [100]NepaliMonthData{ {[12]int8{31, 31, 32, 31, 31, 31, 30, 29, 29, 30, 30, 30}, 365}, // 2099 BS - 2042 AD } +func enMinYear() int { + return int(referenceEnDate[0]) + 1 +} + +func enMaxYear() int { + return int(referenceEnDate[0]) + len(npMonthData) - 1 +} + +func npMinYear() int { + return int(npInitialYear) +} + +func npMaxYear() int { + return int(npInitialYear) + len(npMonthData) - 1 +} + +/* Checks if the english year is leap year or not */ +func isLeapYear(year int) bool { + if year%4 == 0 { + if year%100 == 0 { + return (year%400 == 0) + } + return true + } + return false +} + +func getEnMonths(year int) *[12]int8 { + if isLeapYear(year) { + return &enLeapMonths + } + return &enMonths +} + +/* +Returns diff from the reference with its absolute reference. +Used in function `NepaliToEnglish`. + +Eg. ref: 1943/4/14 - 1943/01/01 +*/ +func getDiffFromEnAbsoluteReference() int { + var diff int = 0 + + // adding sum of month of year till the reference month + months := getEnMonths(int(referenceEnDate[0])) + for i := 0; i < int(referenceEnDate[1])-1; i++ { + diff += int(months[i]) + } + + return diff + int(referenceEnDate[2]) - 1 // added day too +} + // ENGLISH DATE CONVERSION // checks if english date in within range 1944 - 2042 func checkEnglishDate(year int, month int, day int) bool { - if year < 1944 || year > 2042 { + if year < enMinYear() || year > enMaxYear() { return false } if month < 1 || month > 12 { @@ -156,27 +211,27 @@ func getTotalDaysFromEnglishDate(year int, month int, day int) int { // NEPALI DATE CONVERSION -// checks if nepali date is in range 2000-2098 +// checks if nepali date is in range func checkNepaliDate(year int, month int, day int) bool { - if year < 2000 || year > 2098 { + if year < npMinYear() || year > npMaxYear() { return false } if month < 1 || month > 12 { return false } - if day < 1 || day > int(npMonthData[year-2000].monthData[month-1]) { + if day < 1 || day > int(npMonthData[year-int(npInitialYear)].monthData[month-1]) { return false } return true } -// counts and returns total days from the nepali date 2000-01-01 +// counts and returns total days from the nepali initial date func getTotalDaysFromNepaliDate(year int, month int, day int) int { var totalDays int = day - 1 - // adding days of months of 2000 - var yearIndex int = year - 2000 + // adding days of months of initial year + var yearIndex int = year - int(npInitialYear) for i := 0; i < month-1; i++ { totalDays = totalDays + int(npMonthData[yearIndex].monthData[i]) } @@ -188,22 +243,11 @@ func getTotalDaysFromNepaliDate(year int, month int, day int) int { return totalDays } -// checks if the english year is leap year or not""" -func isLeapYear(year int) bool { - if year%4 == 0 { - if year%100 == 0 { - return (year%400 == 0) - } - return true - } - return false -} - // Public methods // Converts english date to nepali. -// Accepts the input parameters year, month, day -// Returns multi value of year, month, day +// Accepts the input parameters year, month, day. +// Returns dates in array and error. func EnglishToNepali(year int, month int, day int) (*[3]int, error) { // VALIDATION // checking if date is in range @@ -212,14 +256,19 @@ func EnglishToNepali(year int, month int, day int) (*[3]int, error) { } // REFERENCE - // Setting nepali reference to 2000/01/01 with english date 1943/04/14 - npYear := 2000 - npMonth := 1 - npDay := 1 + npYear, npMonth, npDay := int(npInitialYear), 1, 1 // DIFFERENCE - // calculating difference days from 1943/04/14 - var difference int = int(math.Abs(float64(getTotalDaysFromEnglishDate(year, month, day) - getTotalDaysFromEnglishDate(1943, 4, 14)))) + // calculating days count from the reference date + var difference int = int( + math.Abs(float64( + getTotalDaysFromEnglishDate( + year, month, day, + ) - getTotalDaysFromEnglishDate( + int(referenceEnDate[0]), int(referenceEnDate[1]), int(referenceEnDate[2]), + ), + )), + ) // YEAR // Incrementing year until the difference remains less than 365 @@ -247,8 +296,8 @@ func EnglishToNepali(year int, month int, day int) (*[3]int, error) { } // Converts nepali date to english. -// Accepts the input parameters year, month, day -// Returns multi value of year, month, day +// Accepts the input parameters year, month, day. +// Returns dates in array and error. func NepaliToEnglish(year int, month int, day int) (*[3]int, error) { // VALIDATION // checking if date is in range @@ -257,14 +306,15 @@ func NepaliToEnglish(year int, month int, day int) (*[3]int, error) { } // REFERENCE - // Setting english reference to 1944/01/01 with nepali date 2000/09/17 - enYear := 1944 - enMonth := 1 - enDay := 1 + // For absolute reference, moving date to Jan 1 + // Eg. ref: 1943/4/14 => 1943/01/01 + enYear, enMonth, enDay := int(referenceEnDate[0]), 1, 1 + // calculating difference from the adjusted reference (eg. 1943/4/14 - 1943/01/01) + referenceDiff := getDiffFromEnAbsoluteReference() // DIFFERENCE - // calculating difference days from 2000/09/17 - var difference int = int(math.Abs(float64(getTotalDaysFromNepaliDate(year, month, day) - getTotalDaysFromNepaliDate(2000, 9, 17)))) + // calculating days count from the reference date + var difference int = getTotalDaysFromNepaliDate(year, month, day) + referenceDiff // YEAR // Incrementing year until the difference remains less than 365 (or 365) @@ -279,10 +329,7 @@ func NepaliToEnglish(year int, month int, day int) (*[3]int, error) { // MONTH // Incrementing month until the difference remains less than next english month (mostly 31) - var monthDays [12]int8 = enMonths - if isLeapYear(enYear) { - monthDays = enLeapMonths - } + monthDays := getEnMonths(enYear) var i int = 0 for difference >= int(monthDays[i]) { diff --git a/dateConverter/converter_test.go b/dateConverter/converter_test.go index 230edce..d26b41c 100644 --- a/dateConverter/converter_test.go +++ b/dateConverter/converter_test.go @@ -67,6 +67,18 @@ func TestEnglishToNepaliReturnsValidFutureNepaliDate(t *testing.T) { assert.EqualValues(t, *date, [3]int{2087, 8, 10}) } +func TestEnglishToNepaliForMinEdgeDate(t *testing.T) { + date, err := dateConverter.EnglishToNepali(1944, 1, 1) + assert.Nil(t, err) + assert.EqualValues(t, *date, [3]int{2000, 9, 17}) +} + +func TestEnglishToNepaliForMaxEdgeDate(t *testing.T) { + date, err := dateConverter.EnglishToNepali(2042, 12, 31) + assert.Nil(t, err) + assert.EqualValues(t, *date, [3]int{2099, 9, 16}) +} + // NepaliToEnglish func TestNepaliToEnglishReturnErrorOnMaxYearRange(t *testing.T) { @@ -128,3 +140,15 @@ func TestNepaliToEnglishReturnsValidEnglishLeapYearDate(t *testing.T) { assert.Nil(t, err) assert.EqualValues(t, *date, [3]int{2024, 3, 28}) } + +func TestNepaliToEnglishForMinEdgeDate(t *testing.T) { + date, err := dateConverter.NepaliToEnglish(2000, 1, 1) + assert.Nil(t, err) + assert.EqualValues(t, *date, [3]int{1943, 4, 14}) +} + +func TestNepaliToEnglishForMaxEdgeDate(t *testing.T) { + date, err := dateConverter.NepaliToEnglish(2099, 12, 30) + assert.Nil(t, err) + assert.EqualValues(t, *date, [3]int{2043, 4, 13}) +}