diff --git a/dateConverter/converter.go b/dateConverter/converter.go index acdad5a..aff84ce 100644 --- a/dateConverter/converter.go +++ b/dateConverter/converter.go @@ -6,6 +6,7 @@ package dateConverter import ( + "time" "errors" "math" ) @@ -13,6 +14,13 @@ import ( // 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} +// A struct for Date +type Date struct { + Year int + Month int + Day int + Calendar string +} type NepaliMonthData struct { monthData [12]int8 @@ -180,31 +188,31 @@ func getDiffFromEnAbsoluteReference() int { // ENGLISH DATE CONVERSION // checks if english date in within range 1944 - 2042 -func checkEnglishDate(year int, month int, day int) bool { - if year < enMinYear() || year > enMaxYear() { +func checkEnglishDate(date Date) bool { + if date.Year < enMinYear() || date.Year > enMaxYear() { return false } - if month < 1 || month > 12 { + if date.Month < 1 || date.Month > 12 { return false } - if day < 1 || day > 31 { + if date.Day < 1 || date.Day > 31 { return false } return true } // counts and returns total days from the date 0000-01-01 -func getTotalDaysFromEnglishDate(year int, month int, day int) int { - var totalDays int = year*365 + day - for i := 0; i < month-1; i++ { +func getTotalDaysFromEnglishDate(date Date) int { + var totalDays int = date.Year*365 + date.Day + for i := 0; i < date.Month-1; i++ { totalDays = totalDays + int(enMonths[i]) } // adding leap days (ie. leap year count) - if month <= 2 { // checking February month (where leap exists) - year -= 1 + if date.Month <= 2 { // checking February month (where leap exists) + date.Year -= 1 } - totalDays += int(year/4) - int(year/100) + int(year/400) + totalDays += int(date.Year/4) - int(date.Year/100) + int(date.Year/400) return totalDays } @@ -212,27 +220,27 @@ func getTotalDaysFromEnglishDate(year int, month int, day int) int { // NEPALI DATE CONVERSION // checks if nepali date is in range -func checkNepaliDate(year int, month int, day int) bool { - if year < npMinYear() || year > npMaxYear() { +func checkNepaliDate(date Date) bool { + if date.Year < npMinYear() || date.Year > npMaxYear() { return false } - if month < 1 || month > 12 { + if date.Month < 1 || date.Month > 12 { return false } - if day < 1 || day > int(npMonthData[year-int(npInitialYear)].monthData[month-1]) { + if date.Day < 1 || date.Day > int(npMonthData[date.Year-int(npInitialYear)].monthData[date.Month-1]) { return false } return true } // counts and returns total days from the nepali initial date -func getTotalDaysFromNepaliDate(year int, month int, day int) int { - var totalDays int = day - 1 +func getTotalDaysFromNepaliDate(date Date) int { + var totalDays int = date.Day - 1 // adding days of months of initial year - var yearIndex int = year - int(npInitialYear) - for i := 0; i < month-1; i++ { + var yearIndex int = date.Year - int(npInitialYear) + for i := 0; i < date.Month-1; i++ { totalDays = totalDays + int(npMonthData[yearIndex].monthData[i]) } @@ -248,34 +256,39 @@ func getTotalDaysFromNepaliDate(year int, month int, day int) int { // Converts english date to nepali. // Accepts the input parameters year, month, day. // Returns dates in array and error. -func EnglishToNepali(year int, month int, day int) (*[3]int, error) { +func EnglishToNepali(year int, month int, day int) (*Date, error) { + // constructing the input date + enDate := Date{ + Year: year, + Month: month, + Day: day, + } // VALIDATION // checking if date is in range - if !checkEnglishDate(year, month, day) { + if !checkEnglishDate(enDate) { return nil, errors.New("date is out of range") } // REFERENCE - npYear, npMonth, npDay := int(npInitialYear), 1, 1 - + // constructing the output date + npDate := Date{ + Year: int(npInitialYear), + Month: 1, + Day: 1, + Calendar: "Nepali", + } // DIFFERENCE // 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]), - ), - )), - ) + getTotalDaysFromEnglishDate(enDate) - getTotalDaysFromEnglishDate(Date{int(referenceEnDate[0]), int(referenceEnDate[1]), int(referenceEnDate[2]), ""})))) // YEAR // Incrementing year until the difference remains less than 365 var yearDataIndex int = 0 for difference >= int(npMonthData[yearDataIndex].yearDays) { difference -= int(npMonthData[yearDataIndex].yearDays) - npYear += 1 + npDate.Year += 1 yearDataIndex += 1 } @@ -284,63 +297,91 @@ func EnglishToNepali(year int, month int, day int) (*[3]int, error) { var i int = 0 for difference >= int(npMonthData[yearDataIndex].monthData[i]) { difference -= int(npMonthData[yearDataIndex].monthData[i]) - npMonth += 1 + npDate.Month += 1 i += 1 } // DAY // Remaining difference is the day - npDay += difference + npDate.Day += difference - return &[3]int{npYear, npMonth, npDay}, nil + return &npDate, nil } // Converts nepali date to english. // Accepts the input parameters year, month, day. // Returns dates in array and error. -func NepaliToEnglish(year int, month int, day int) (*[3]int, error) { +func NepaliToEnglish(year int, month int, day int) (*Date, error) { + // constructing the input date + npDate := Date{ + Year: year, + Month: month, + Day: day, + } // VALIDATION // checking if date is in range - if !checkNepaliDate(year, month, day) { + if !checkNepaliDate(npDate) { return nil, errors.New("date is out of range") } // REFERENCE // For absolute reference, moving date to Jan 1 // Eg. ref: 1943/4/14 => 1943/01/01 - enYear, enMonth, enDay := int(referenceEnDate[0]), 1, 1 + // constructing the output date + enDate := Date{ + Year: int(referenceEnDate[0]), + Month: 1, + Day: 1, + Calendar: "English", + } // calculating difference from the adjusted reference (eg. 1943/4/14 - 1943/01/01) referenceDiff := getDiffFromEnAbsoluteReference() // DIFFERENCE // calculating days count from the reference date - var difference int = getTotalDaysFromNepaliDate(year, month, day) + referenceDiff + var difference int = getTotalDaysFromNepaliDate(npDate) + referenceDiff // YEAR // Incrementing year until the difference remains less than 365 (or 365) - for (difference >= 366 && isLeapYear(enYear)) || (difference >= 365 && !(isLeapYear(enYear))) { - if isLeapYear(enYear) { + for (difference >= 366 && isLeapYear(enDate.Year)) || (difference >= 365 && !(isLeapYear(enDate.Year))) { + if isLeapYear(enDate.Year) { difference -= 366 } else { difference -= 365 } - enYear += 1 + enDate.Year += 1 } // MONTH // Incrementing month until the difference remains less than next english month (mostly 31) - monthDays := getEnMonths(enYear) + monthDays := getEnMonths(enDate.Year) var i int = 0 for difference >= int(monthDays[i]) { difference -= int(monthDays[i]) - enMonth += 1 + enDate.Month += 1 i += 1 } // DAY // Remaining difference is the day - enDay += difference + enDate.Day += difference + + return &enDate, nil +} - return &[3]int{enYear, enMonth, enDay}, nil +// Weekday returns the weekday of the date. +func (d *Date) Weekday() string { + var t time.Time + if d.Calendar == "Nepali" { + // Convert the Nepali date to English + convertedEnDate, _ := NepaliToEnglish(d.Year, d.Month, d.Day) + // Construct a time.Time object from the converted English date + t = time.Date(convertedEnDate.Year, time.Month(convertedEnDate.Month), convertedEnDate.Day, 0, 0, 0, 0, time.UTC) + } else { + // Construct a time.Time object from the English date + t = time.Date(d.Year, time.Month(d.Month), d.Day, 0, 0, 0, 0, time.UTC) + } + // Use the Weekday() function from the time package to get the weekday + return t.Weekday().String() } diff --git a/dateConverter/converter_test.go b/dateConverter/converter_test.go index d26b41c..1646e94 100644 --- a/dateConverter/converter_test.go +++ b/dateConverter/converter_test.go @@ -52,31 +52,35 @@ func TestEnglishToNepaliReturnErrorOnMaxDayRange(t *testing.T) { func TestEnglishToNepaliReturnsValidPastNepaliDate(t *testing.T) { date, err := dateConverter.EnglishToNepali(1994, 8, 13) assert.Nil(t, err) - assert.EqualValues(t, *date, [3]int{2051, 4, 29}) + assert.EqualValues(t, *date, dateConverter.Date{2051, 4, 29, "Nepali"}) + assert.EqualValues(t, date.Weekday(), "Saturday") } func TestEnglishToNepaliReturnsValidRecentNepaliDate(t *testing.T) { date, err := dateConverter.EnglishToNepali(2023, 1, 28) assert.Nil(t, err) - assert.EqualValues(t, *date, [3]int{2079, 10, 14}) + assert.EqualValues(t, *date, dateConverter.Date{2079, 10, 14, "Nepali"}) + assert.EqualValues(t, date.Weekday(), "Saturday") } func TestEnglishToNepaliReturnsValidFutureNepaliDate(t *testing.T) { date, err := dateConverter.EnglishToNepali(2030, 11, 26) assert.Nil(t, err) - assert.EqualValues(t, *date, [3]int{2087, 8, 10}) + assert.EqualValues(t, *date, dateConverter.Date{2087, 8, 10, "Nepali"}) + assert.EqualValues(t, date.Weekday(), "Tuesday") } 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}) + assert.EqualValues(t, *date, dateConverter.Date{2000, 9, 17, "Nepali"}) + assert.EqualValues(t, date.Weekday(), "Saturday") } 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}) + assert.EqualValues(t, *date, dateConverter.Date{2099, 9, 16, "Nepali"}) } // NepaliToEnglish @@ -120,35 +124,49 @@ func TestNepaliToEnglishReturnErrorOnMaxDayRange(t *testing.T) { func TestNepaliToEnglishReturnsValidPastEnglishDate(t *testing.T) { date, err := dateConverter.NepaliToEnglish(2051, 4, 29) assert.Nil(t, err) - assert.EqualValues(t, *date, [3]int{1994, 8, 13}) + assert.EqualValues(t, *date, dateConverter.Date{1994, 8, 13, "English"}) + assert.EqualValues(t, date.Weekday(), "Saturday") } func TestNepaliToEnglishReturnsValidRecentEnglishDate(t *testing.T) { date, err := dateConverter.NepaliToEnglish(2079, 10, 14) assert.Nil(t, err) - assert.EqualValues(t, *date, [3]int{2023, 1, 28}) + assert.EqualValues(t, *date, dateConverter.Date{2023, 1, 28, "English"}) + assert.EqualValues(t, date.Weekday(), "Saturday") } func TestNepaliToEnglishReturnsValidFutureEnglishDate(t *testing.T) { date, err := dateConverter.NepaliToEnglish(2087, 8, 10) assert.Nil(t, err) - assert.EqualValues(t, *date, [3]int{2030, 11, 26}) + assert.EqualValues(t, *date, dateConverter.Date{2030, 11, 26, "English"}) + assert.EqualValues(t, date.Weekday(), "Tuesday") } func TestNepaliToEnglishReturnsValidEnglishLeapYearDate(t *testing.T) { date, err := dateConverter.NepaliToEnglish(2080, 12, 15) assert.Nil(t, err) - assert.EqualValues(t, *date, [3]int{2024, 3, 28}) + assert.EqualValues(t, *date, dateConverter.Date{2024, 3, 28, "English"}) + assert.EqualValues(t, date.Weekday(), "Thursday") } 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}) + assert.EqualValues(t, *date, dateConverter.Date{1943, 4, 14, "English"}) + assert.EqualValues(t, date.Weekday(), "Wednesday") } 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}) + assert.EqualValues(t, *date, dateConverter.Date{2043, 4, 13, "English"}) } + +// Week Day +func TestWeekdayForSameDateInBothCalendars(t *testing.T) { + enDate := dateConverter.Date{Year: 2024, Month: 3, Day: 31} + npDate, err := dateConverter.EnglishToNepali(enDate.Year, enDate.Month, enDate.Day) + assert.Nil(t, err) + assert.Equal(t, enDate.Weekday(), npDate.Weekday()) +} +