Skip to content

Commit

Permalink
Refactored with Date struct and added Weekday Method
Browse files Browse the repository at this point in the history
  • Loading branch information
arjnepwebsites committed Mar 31, 2024
1 parent 69c6a5a commit 964a0be
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 55 deletions.
129 changes: 85 additions & 44 deletions dateConverter/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@
package dateConverter

import (
"time"
"errors"
"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}
// A struct for Date
type Date struct {
Year int
Month int
Day int
Calendar string
}

type NepaliMonthData struct {
monthData [12]int8
Expand Down Expand Up @@ -180,59 +188,59 @@ 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
}

// 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])
}

Expand All @@ -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
}

Expand All @@ -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()
}
40 changes: 29 additions & 11 deletions dateConverter/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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())
}

0 comments on commit 964a0be

Please sign in to comment.