github.com/go-chrono/chrono@v0.0.0-20240102183611-532f0d0d7c34/local_date_test.go (about)

     1  package chrono_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/go-chrono/chrono"
     8  )
     9  
    10  func TestLocalDate(t *testing.T) {
    11  	for _, tt := range []struct {
    12  		year       int
    13  		month      chrono.Month
    14  		day        int
    15  		weekday    chrono.Weekday
    16  		isLeapYear bool
    17  		yearDay    int
    18  		isoYear    int
    19  		isoWeek    int
    20  	}{
    21  		{-4713, chrono.November, 24, chrono.Monday, false, 328, -4713, 48}, // 4714 BCE
    22  		{+5874898, chrono.June, 3, chrono.Tuesday, false, 154, +5874898, 23},
    23  		{+1858, chrono.November, 17, chrono.Wednesday, false, 321, +1858, 46},
    24  		{+1968, chrono.May, 24, chrono.Friday, true, 145, +1968, 21},
    25  		{+1950, chrono.January, 1, chrono.Sunday, false, 1, +1949, 52},
    26  		{+1958, chrono.January, 1, chrono.Wednesday, false, 1, +1958, 1},
    27  		{+1582, chrono.October, 15, chrono.Friday, false, 288, +1582, 41},
    28  		{+1, chrono.January, 1, chrono.Monday, false, 1, +1, 1},
    29  		{+1970, chrono.January, 1, chrono.Thursday, false, 1, +1970, 1},
    30  		{+200, chrono.March, 1, chrono.Saturday, false, 60, +200, 9},
    31  		{+2020, chrono.December, 31, chrono.Thursday, true, 366, +2020, 53},
    32  		{+2021, chrono.January, 1, chrono.Friday, false, 1, +2020, 53},
    33  		{+2000, chrono.February, 29, chrono.Tuesday, true, 60, +2000, 9},
    34  		{+2000, chrono.March, 1, chrono.Wednesday, true, 61, +2000, 9},
    35  	} {
    36  		t.Run(fmt.Sprintf("%+05d-%02d-%02d", tt.year, tt.month, tt.day), func(t *testing.T) {
    37  			date := chrono.LocalDateOf(tt.year, tt.month, tt.day)
    38  
    39  			year, month, day := date.Date()
    40  			if year != tt.year {
    41  				t.Errorf("date.Date() year = %d, want %d", year, tt.year)
    42  			}
    43  
    44  			if month != tt.month {
    45  				t.Errorf("date.Date() month = %s, want %s", month, tt.month)
    46  			}
    47  
    48  			if day != tt.day {
    49  				t.Errorf("date.Date() day = %d, want %d", day, tt.day)
    50  			}
    51  
    52  			if weekday := date.Weekday(); weekday != tt.weekday {
    53  				t.Errorf("date.Weekday() = %s, want %s", weekday, tt.weekday)
    54  			}
    55  
    56  			if isLeapYear := date.IsLeapYear(); isLeapYear != tt.isLeapYear {
    57  				t.Errorf("date.YearDay() = %t, want %t", isLeapYear, tt.isLeapYear)
    58  			}
    59  
    60  			if yearDay := date.YearDay(); yearDay != tt.yearDay {
    61  				t.Errorf("date.YearDay() = %d, want %d", yearDay, tt.yearDay)
    62  			}
    63  
    64  			isoYear, isoWeek := date.ISOWeek()
    65  			if isoYear != tt.isoYear {
    66  				t.Errorf("date.ISOWeek() year = %d, want %d", isoYear, tt.isoYear)
    67  			}
    68  
    69  			if isoWeek != tt.isoWeek {
    70  				t.Errorf("date.ISOWeek() week = %d, want %d", isoWeek, tt.isoWeek)
    71  			}
    72  		})
    73  	}
    74  }
    75  
    76  func TestLocalDateOf(t *testing.T) {
    77  	for _, tt := range []struct {
    78  		name  string
    79  		year  int
    80  		month chrono.Month
    81  		day   int
    82  	}{
    83  		{"year underflows", -4714, chrono.January, 1},
    84  		{"year & month underflows", -4713, chrono.October, 1},
    85  		{"year & month & day underflows", -4713, chrono.November, 23},
    86  		{"year overflows", 5874899, chrono.January, 1},
    87  		{"year & month overflows", 5874898, chrono.July, 1},
    88  		{"year & month & day overflows", 5874898, chrono.June, 4},
    89  		{"month underflows", 2001, 0, 1},
    90  		{"month overflows", 2001, 13, 1},
    91  		{"day underflows", 2001, chrono.February, 0},
    92  		{"day overflows", 2001, chrono.February, 29},
    93  		{"day overflows leap year", 2004, chrono.February, 30},
    94  	} {
    95  		t.Run(tt.name, func(t *testing.T) {
    96  			func() {
    97  				defer func() {
    98  					if r := recover(); r == nil {
    99  						t.Error("expecting panic that didn't occur")
   100  					}
   101  				}()
   102  
   103  				chrono.LocalDateOf(tt.year, tt.month, tt.day)
   104  			}()
   105  		})
   106  	}
   107  }
   108  
   109  func TestOfDayOfYear(t *testing.T) {
   110  	for _, tt := range []struct {
   111  		year     int
   112  		day      int
   113  		expected chrono.LocalDate
   114  	}{
   115  		{2020, 60, chrono.LocalDateOf(2020, chrono.February, 29)},
   116  		{2021, 60, chrono.LocalDateOf(2021, chrono.March, 1)},
   117  		{2020, 120, chrono.LocalDateOf(2020, chrono.April, 29)},
   118  		{2021, 120, chrono.LocalDateOf(2021, chrono.April, 30)},
   119  	} {
   120  		t.Run(fmt.Sprintf("%04d-%03d", tt.year, tt.day), func(t *testing.T) {
   121  			if date := chrono.OfDayOfYear(tt.year, tt.day); date != tt.expected {
   122  				t.Errorf("OfDayOfYear(%d, %d) = %s, want %s", tt.year, tt.day, date, tt.expected)
   123  			}
   124  		})
   125  	}
   126  }
   127  
   128  func TestOfFirstWeekday(t *testing.T) {
   129  	for _, tt := range []struct {
   130  		year     int
   131  		month    chrono.Month
   132  		weekday  chrono.Weekday
   133  		expected chrono.LocalDate
   134  	}{
   135  		{2020, chrono.January, chrono.Wednesday, chrono.LocalDateOf(2020, chrono.January, 1)},
   136  		{2020, chrono.January, chrono.Monday, chrono.LocalDateOf(2020, chrono.January, 6)},
   137  		{2020, chrono.March, chrono.Sunday, chrono.LocalDateOf(2020, chrono.March, 1)},
   138  	} {
   139  		t.Run(fmt.Sprintf("%04d-%s %s", tt.year, tt.month, tt.weekday), func(t *testing.T) {
   140  			if date := chrono.OfFirstWeekday(tt.year, tt.month, tt.weekday); date != tt.expected {
   141  				t.Errorf("OfFirstWeekday(%d, %s, %s) = %s, want %s", tt.year, tt.month, tt.weekday, date, tt.expected)
   142  			} else if weekday := date.Weekday(); weekday != tt.weekday {
   143  				t.Errorf("weekday = %s, want %s", weekday, tt.weekday)
   144  			}
   145  		})
   146  	}
   147  }
   148  
   149  func TestOfISOWeek(t *testing.T) {
   150  	for _, tt := range []struct {
   151  		isoYear  int
   152  		isoWeek  int
   153  		weekday  chrono.Weekday
   154  		expected chrono.LocalDate
   155  	}{
   156  		{1936, 51, chrono.Monday, chrono.LocalDateOf(1936, chrono.December, 14)},
   157  		{1949, 52, chrono.Sunday, chrono.LocalDateOf(1950, chrono.January, 1)},
   158  		{2020, 53, chrono.Friday, chrono.LocalDateOf(2021, chrono.January, 1)},
   159  	} {
   160  		t.Run(fmt.Sprintf("%04d-W%02d-%d", tt.isoYear, tt.isoWeek, tt.weekday), func(t *testing.T) {
   161  			if date, err := chrono.OfISOWeek(tt.isoYear, tt.isoWeek, tt.weekday); err != nil {
   162  				t.Errorf("failed to calculate date from ISO week: %v", err)
   163  			} else if date != tt.expected {
   164  				t.Errorf("OfISOWeek(%d, %d, %s) = %s, want %s", tt.isoYear, tt.isoWeek, tt.weekday, date, tt.expected)
   165  			}
   166  		})
   167  	}
   168  }
   169  
   170  func TestLocalDate_Date(t *testing.T) {
   171  	for _, tt := range []struct {
   172  		name  string
   173  		date  chrono.LocalDate
   174  		year  int
   175  		month chrono.Month
   176  		day   int
   177  	}{
   178  		{"default value", chrono.LocalDate(0), 1970, chrono.January, 1},
   179  		{"minimum value", chrono.MinLocalDate(), -4713, chrono.November, 24},
   180  		{"maximum value", chrono.MaxLocalDate(), 5874898, chrono.June, 3},
   181  	} {
   182  		t.Run(tt.name, func(t *testing.T) {
   183  			year, month, day := tt.date.Date()
   184  			if year != tt.year {
   185  				t.Errorf("date.Date() year = %d, want %d", year, tt.year)
   186  			}
   187  
   188  			if month != tt.month {
   189  				t.Errorf("date.Date() month = %s, want %s", month, tt.month)
   190  			}
   191  
   192  			if day != tt.day {
   193  				t.Errorf("date.Date() day = %d, want %d", day, tt.day)
   194  			}
   195  		})
   196  	}
   197  
   198  	for _, tt := range []struct {
   199  		name string
   200  		date chrono.LocalDate
   201  	}{
   202  		{"underflows", chrono.MinLocalDate() - 1},
   203  		{"overflows", chrono.MaxLocalDate() + 1},
   204  	} {
   205  		t.Run(tt.name, func(t *testing.T) {
   206  			func() {
   207  				defer func() {
   208  					if r := recover(); r == nil {
   209  						t.Error("expecting panic that didn't occur")
   210  					}
   211  				}()
   212  
   213  				tt.date.Date()
   214  			}()
   215  		})
   216  	}
   217  }
   218  
   219  func TestLocalDate_AddDate(t *testing.T) {
   220  	for _, tt := range []struct {
   221  		name      string
   222  		date      chrono.LocalDate
   223  		addYears  int
   224  		addMonths int
   225  		addDays   int
   226  		expected  chrono.LocalDate
   227  	}{
   228  		{"nothing", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, 0, chrono.LocalDateOf(2020, chrono.March, 18)},
   229  		{"add years", chrono.LocalDateOf(2020, chrono.March, 18), 105, 0, 0, chrono.LocalDateOf(2125, chrono.March, 18)},
   230  		{"sub years", chrono.LocalDateOf(2020, chrono.March, 18), -280, 0, 0, chrono.LocalDateOf(1740, chrono.March, 18)},
   231  		{"add months", chrono.LocalDateOf(2020, chrono.March, 18), 0, 6, 0, chrono.LocalDateOf(2020, chrono.September, 18)},
   232  		{"sub months", chrono.LocalDateOf(2020, chrono.March, 18), 0, -2, 0, chrono.LocalDateOf(2020, chrono.January, 18)},
   233  		{"add days", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, 8, chrono.LocalDateOf(2020, chrono.March, 26)},
   234  		{"sub days", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, -15, chrono.LocalDateOf(2020, chrono.March, 3)},
   235  		{"time package example", chrono.LocalDateOf(2011, chrono.January, 1), -1, 2, 3, chrono.LocalDateOf(2010, chrono.March, 4)},
   236  		{"normalized time package example", chrono.LocalDateOf(2011, chrono.October, 31), 0, 1, 0, chrono.LocalDateOf(2011, chrono.December, 1)},
   237  		{"wrap around day", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, 20, chrono.LocalDateOf(2020, chrono.April, 7)},
   238  	} {
   239  		t.Run(tt.name, func(t *testing.T) {
   240  			if ok := tt.date.CanAddDate(tt.addYears, tt.addMonths, tt.addDays); !ok {
   241  				t.Errorf("date = %s, date.CanAdd(%d, %d, %d) = false, want true", tt.date, tt.addYears, tt.addMonths, tt.addDays)
   242  			}
   243  
   244  			if date := tt.date.AddDate(tt.addYears, tt.addMonths, tt.addDays); date != tt.expected {
   245  				t.Errorf("date = %s, date.Add(%d, %d, %d) = %s, want %s", tt.date, tt.addYears, tt.addMonths, tt.addDays, date, tt.expected)
   246  			}
   247  		})
   248  	}
   249  
   250  	for _, tt := range []struct {
   251  		name    string
   252  		date    chrono.LocalDate
   253  		addDays int
   254  	}{
   255  		{"underflow", chrono.MinLocalDate(), -1},
   256  		{"overflow", chrono.MaxLocalDate(), 1},
   257  	} {
   258  		t.Run(tt.name, func(t *testing.T) {
   259  			if ok := tt.date.CanAddDate(0, 0, tt.addDays); ok {
   260  				t.Errorf("date = %s, date.CanAdd(0, 0, %d) = true, want false", tt.date, tt.addDays)
   261  			}
   262  
   263  			func() {
   264  				defer func() {
   265  					if r := recover(); r == nil {
   266  						t.Error("expecting panic that didn't occur")
   267  					}
   268  				}()
   269  
   270  				tt.date.AddDate(0, 0, tt.addDays)
   271  			}()
   272  		})
   273  	}
   274  }