github.com/go-chrono/chrono@v0.0.0-20240102183611-532f0d0d7c34/offset_date_time_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 TestOffsetDateTimeOf(t *testing.T) {
    11  	for _, tt := range []struct {
    12  		datetime     chrono.OffsetDateTime
    13  		expectedDate chrono.LocalDate
    14  		expectedTime chrono.OffsetTime
    15  	}{
    16  		{
    17  			datetime:     chrono.OffsetDateTime{},
    18  			expectedDate: chrono.LocalDateOf(1970, chrono.January, 1),
    19  			expectedTime: chrono.OffsetTimeOf(0, 0, 0, 0, 0, 0),
    20  		},
    21  		{
    22  			datetime:     chrono.OffsetDateTimeOf(2020, chrono.March, 18, 12, 30, 0, 100000000, 0, 0),
    23  			expectedDate: chrono.LocalDateOf(2020, chrono.March, 18),
    24  			expectedTime: chrono.OffsetTimeOf(12, 30, 0, 100000000, 0, 0),
    25  		},
    26  	} {
    27  		t.Run(tt.datetime.String(), func(t *testing.T) {
    28  			date, time := tt.datetime.Split()
    29  			if date != tt.expectedDate {
    30  				t.Errorf("datetime.Split() date = %s, want %s", date, tt.expectedDate)
    31  			}
    32  
    33  			if time.Compare(tt.expectedTime) != 0 {
    34  				t.Errorf("datetime.Split() time = %s, want %s", time, tt.expectedTime)
    35  			}
    36  		})
    37  	}
    38  }
    39  
    40  func TestOfLocalDateOffsetTime(t *testing.T) {
    41  	datetime := chrono.OfLocalDateOffsetTime(
    42  		chrono.LocalDateOf(2020, chrono.March, 18),
    43  		chrono.OffsetTimeOf(12, 30, 0, 100000000, -2, 30),
    44  	)
    45  
    46  	date, time := datetime.Split()
    47  	if expected := chrono.LocalDateOf(2020, chrono.March, 18); date != expected {
    48  		t.Errorf("datetime.Split() date = %s, want %s", date, expected)
    49  	}
    50  
    51  	if expected := chrono.OffsetTimeOf(12, 30, 0, 100000000, -2, 30); time != expected {
    52  		t.Errorf("datetime.Split() time = %s, want %s", time, expected)
    53  	}
    54  }
    55  
    56  func TestOfLocalDateTimeOffset(t *testing.T) {
    57  	datetime := chrono.OfLocalDateTimeOffset(
    58  		chrono.LocalDateOf(2020, chrono.March, 18),
    59  		chrono.LocalTimeOf(12, 30, 0, 100000000),
    60  		chrono.Extent(chrono.OffsetOf(-2, 30)),
    61  	)
    62  
    63  	date, time := datetime.Split()
    64  	if expected := chrono.LocalDateOf(2020, chrono.March, 18); date != expected {
    65  		t.Errorf("datetime.Split() date = %s, want %s", date, expected)
    66  	}
    67  
    68  	if expected := chrono.OffsetTimeOf(12, 30, 0, 100000000, -2, 30); time != expected {
    69  		t.Errorf("datetime.Split() time = %s, want %s", time, expected)
    70  	}
    71  }
    72  
    73  func TestOffsetDateTime_Compare(t *testing.T) {
    74  	for _, tt := range []struct {
    75  		name     string
    76  		d        chrono.OffsetDateTime
    77  		d2       chrono.OffsetDateTime
    78  		expected int
    79  	}{
    80  		{"earlier", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 11, 0, 0, 0, -2, 30), chrono.OffsetDateTimeOf(2020, chrono.March, 18, 12, 0, 0, 0, -2, 30), -1},
    81  		{"later", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 13, 30, 0, 0, -2, 30), chrono.OffsetDateTimeOf(2020, chrono.March, 18, 13, 29, 55, 0, -2, 30), 1},
    82  		{"equal", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 15, 0, 0, 1000, -2, 30), chrono.OffsetDateTimeOf(2020, chrono.March, 18, 15, 0, 0, 1000, -2, 30), 0},
    83  	} {
    84  		t.Run(tt.name, func(t *testing.T) {
    85  			if v := tt.d.Compare(tt.d2); v != tt.expected {
    86  				t.Errorf("t.Compare(t2) = %d, want %d", v, tt.expected)
    87  			}
    88  		})
    89  	}
    90  }
    91  
    92  func TestOffsetDateTime_Add(t *testing.T) {
    93  	t.Run("valid add", func(t *testing.T) {
    94  		datetime := chrono.OffsetDateTimeOf(2020, chrono.March, 18, 12, 30, 0, 0, -2, 0)
    95  		duration := chrono.DurationOf(48*chrono.Hour + 1000*chrono.Nanosecond)
    96  
    97  		if !datetime.CanAdd(duration) {
    98  			t.Errorf("datetime = %s, datetime.CanAdd(%s) = false, want true", datetime, duration)
    99  		}
   100  
   101  		added := datetime.Add(duration)
   102  		expected := chrono.OffsetDateTimeOf(2020, chrono.March, 20, 12, 30, 0, 1000, -2, 30)
   103  
   104  		if added.Compare(expected) != 0 {
   105  			t.Errorf("datetime = %s, datetime.Add(%s) = %s, want %s", datetime, duration, added, expected)
   106  		}
   107  	})
   108  
   109  	t.Run("invalid add to low", func(t *testing.T) {
   110  		datetime := chrono.MinLocalDateTime().UTC()
   111  		duration := chrono.DurationOf(-1 * chrono.Nanosecond)
   112  
   113  		if datetime.CanAdd(duration) {
   114  			t.Errorf("datetime = %s, datetime.CanAdd(%s) = true, want false", datetime, duration)
   115  		}
   116  
   117  		func() {
   118  			defer func() {
   119  				if r := recover(); r == nil {
   120  					t.Error("expecting panic that didn't occur")
   121  				}
   122  			}()
   123  
   124  			datetime.Add(duration)
   125  		}()
   126  	})
   127  
   128  	t.Run("invalid add to high", func(t *testing.T) {
   129  		datetime := chrono.MaxLocalDateTime().UTC()
   130  		duration := chrono.DurationOf(1 * chrono.Nanosecond)
   131  
   132  		if datetime.CanAdd(duration) {
   133  			t.Errorf("datetime = %s, datetime.CanAdd(%s) = true, want false", datetime, duration)
   134  		}
   135  
   136  		func() {
   137  			defer func() {
   138  				if r := recover(); r == nil {
   139  					t.Error("expecting panic that didn't occur")
   140  				}
   141  			}()
   142  
   143  			datetime.Add(duration)
   144  		}()
   145  	})
   146  }
   147  
   148  func TestOffsetDateTime_AddDate(t *testing.T) {
   149  	for _, tt := range []struct {
   150  		name      string
   151  		datetime  chrono.OffsetDateTime
   152  		addYears  int
   153  		addMonths int
   154  		addDays   int
   155  		expected  chrono.OffsetDateTime
   156  	}{
   157  		{"nothing", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), 0, 0, 0, chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30)},
   158  		{"add years", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), 105, 0, 0, chrono.OffsetDateTimeOf(2125, chrono.March, 18, 0, 0, 0, 0, -2, 30)},
   159  		{"sub years", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), -280, 0, 0, chrono.OffsetDateTimeOf(1740, chrono.March, 18, 0, 0, 0, 0, -2, 30)},
   160  		{"add months", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), 0, 6, 0, chrono.OffsetDateTimeOf(2020, chrono.September, 18, 0, 0, 0, 0, -2, 30)},
   161  		{"sub months", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), 0, -2, 0, chrono.OffsetDateTimeOf(2020, chrono.January, 18, 0, 0, 0, 0, -2, 30)},
   162  		{"add days", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), 0, 0, 8, chrono.OffsetDateTimeOf(2020, chrono.March, 26, 0, 0, 0, 0, -2, 30)},
   163  		{"sub days", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), 0, 0, -15, chrono.OffsetDateTimeOf(2020, chrono.March, 3, 0, 0, 0, 0, -2, 30)},
   164  		{"time package example", chrono.OffsetDateTimeOf(2011, chrono.January, 1, 0, 0, 0, 0, -2, 30), -1, 2, 3, chrono.OffsetDateTimeOf(2010, chrono.March, 4, 0, 0, 0, 0, -2, 30)},
   165  		{"normalized time package example", chrono.OffsetDateTimeOf(2011, chrono.October, 31, 0, 0, 0, 0, -2, 30), 0, 1, 0, chrono.OffsetDateTimeOf(2011, chrono.December, 1, 0, 0, 0, 0, -2, 30)},
   166  		{"wrap around day", chrono.OffsetDateTimeOf(2020, chrono.March, 18, 0, 0, 0, 0, -2, 30), 0, 0, 20, chrono.OffsetDateTimeOf(2020, chrono.April, 7, 0, 0, 0, 0, -2, 30)},
   167  	} {
   168  		t.Run(tt.name, func(t *testing.T) {
   169  			if ok := tt.datetime.CanAddDate(tt.addYears, tt.addMonths, tt.addDays); !ok {
   170  				t.Errorf("date = %s, date.CanAddDate(%d, %d, %d) = false, want true", tt.datetime, tt.addYears, tt.addMonths, tt.addDays)
   171  			}
   172  
   173  			if date := tt.datetime.AddDate(tt.addYears, tt.addMonths, tt.addDays); date.Compare(tt.expected) != 0 {
   174  				t.Errorf("date = %s, date.AddDate(%d, %d, %d) = %s, want %s", tt.datetime, tt.addYears, tt.addMonths, tt.addDays, date, tt.expected)
   175  			}
   176  		})
   177  	}
   178  
   179  	for _, tt := range []struct {
   180  		name     string
   181  		datetime chrono.OffsetDateTime
   182  		addDays  int
   183  	}{
   184  		{"underflow", chrono.MinLocalDateTime().UTC(), -1},
   185  		{"overflow", chrono.MaxLocalDateTime().UTC(), 1},
   186  	} {
   187  		t.Run(tt.name, func(t *testing.T) {
   188  			if ok := tt.datetime.CanAddDate(0, 0, tt.addDays); ok {
   189  				t.Errorf("date = %s, date.CanAddDate(0, 0, %d) = true, want false", tt.datetime, tt.addDays)
   190  			}
   191  
   192  			func() {
   193  				defer func() {
   194  					if r := recover(); r == nil {
   195  						t.Error("expecting panic that didn't occur")
   196  					}
   197  				}()
   198  
   199  				tt.datetime.AddDate(0, 0, tt.addDays)
   200  			}()
   201  		})
   202  	}
   203  }
   204  
   205  func TestOffsetDateTime_Sub(t *testing.T) {
   206  	for _, tt := range []struct {
   207  		dt1  chrono.OffsetDateTime
   208  		dt2  chrono.OffsetDateTime
   209  		diff chrono.Duration
   210  	}{
   211  		{
   212  			chrono.OffsetDateTimeOf(2020, chrono.January, 5, 12, 0, 0, 0, 4, 30),
   213  			chrono.OffsetDateTimeOf(2020, chrono.January, 3, 6, 0, 0, 0, 2, 0),
   214  			chrono.DurationOf(56*chrono.Hour + 30*chrono.Minute),
   215  		},
   216  		{
   217  			chrono.OffsetDateTimeOf(2020, chrono.January, 5, 12, 0, 0, 22, 0, 0),
   218  			chrono.OffsetDateTimeOf(2020, chrono.January, 5, 12, 0, 0, 40, 0, 0),
   219  			chrono.DurationOf(-18 * chrono.Nanosecond),
   220  		},
   221  	} {
   222  		t.Run(fmt.Sprintf("%s - %s", tt.dt1, tt.dt2), func(t *testing.T) {
   223  			if d := tt.dt1.Sub(tt.dt2); d.Compare(tt.diff) != 0 {
   224  				t.Errorf("dt1.Sub(dt2) = %v, want %v", d, tt.diff)
   225  			}
   226  		})
   227  	}
   228  }