...

Source file src/time/zoneinfo_test.go

Documentation: time

		 1  // Copyright 2014 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  package time_test
		 6  
		 7  import (
		 8  	"errors"
		 9  	"fmt"
		10  	"os"
		11  	"reflect"
		12  	"testing"
		13  	"time"
		14  )
		15  
		16  func init() {
		17  	if time.ZoneinfoForTesting() != nil {
		18  		panic(fmt.Errorf("zoneinfo initialized before first LoadLocation"))
		19  	}
		20  }
		21  
		22  func TestEnvVarUsage(t *testing.T) {
		23  	time.ResetZoneinfoForTesting()
		24  
		25  	const testZoneinfo = "foo.zip"
		26  	const env = "ZONEINFO"
		27  
		28  	t.Setenv(env, testZoneinfo)
		29  
		30  	// Result isn't important, we're testing the side effect of this command
		31  	time.LoadLocation("Asia/Jerusalem")
		32  	defer time.ResetZoneinfoForTesting()
		33  
		34  	if zoneinfo := time.ZoneinfoForTesting(); testZoneinfo != *zoneinfo {
		35  		t.Errorf("zoneinfo does not match env variable: got %q want %q", *zoneinfo, testZoneinfo)
		36  	}
		37  }
		38  
		39  func TestBadLocationErrMsg(t *testing.T) {
		40  	time.ResetZoneinfoForTesting()
		41  	loc := "Asia/SomethingNotExist"
		42  	want := errors.New("unknown time zone " + loc)
		43  	_, err := time.LoadLocation(loc)
		44  	if err.Error() != want.Error() {
		45  		t.Errorf("LoadLocation(%q) error = %v; want %v", loc, err, want)
		46  	}
		47  }
		48  
		49  func TestLoadLocationValidatesNames(t *testing.T) {
		50  	time.ResetZoneinfoForTesting()
		51  	const env = "ZONEINFO"
		52  	t.Setenv(env, "")
		53  
		54  	bad := []string{
		55  		"/usr/foo/Foo",
		56  		"\\UNC\foo",
		57  		"..",
		58  		"a..",
		59  	}
		60  	for _, v := range bad {
		61  		_, err := time.LoadLocation(v)
		62  		if err != time.ErrLocation {
		63  			t.Errorf("LoadLocation(%q) error = %v; want ErrLocation", v, err)
		64  		}
		65  	}
		66  }
		67  
		68  func TestVersion3(t *testing.T) {
		69  	time.ForceZipFileForTesting(true)
		70  	defer time.ForceZipFileForTesting(false)
		71  	_, err := time.LoadLocation("Asia/Jerusalem")
		72  	if err != nil {
		73  		t.Fatal(err)
		74  	}
		75  }
		76  
		77  // Test that we get the correct results for times before the first
		78  // transition time. To do this we explicitly check early dates in a
		79  // couple of specific timezones.
		80  func TestFirstZone(t *testing.T) {
		81  	time.ForceZipFileForTesting(true)
		82  	defer time.ForceZipFileForTesting(false)
		83  
		84  	const format = "Mon, 02 Jan 2006 15:04:05 -0700 (MST)"
		85  	var tests = []struct {
		86  		zone	string
		87  		unix	int64
		88  		want1 string
		89  		want2 string
		90  	}{
		91  		{
		92  			"PST8PDT",
		93  			-1633269601,
		94  			"Sun, 31 Mar 1918 01:59:59 -0800 (PST)",
		95  			"Sun, 31 Mar 1918 03:00:00 -0700 (PDT)",
		96  		},
		97  		{
		98  			"Pacific/Fakaofo",
		99  			1325242799,
	 100  			"Thu, 29 Dec 2011 23:59:59 -1100 (-11)",
	 101  			"Sat, 31 Dec 2011 00:00:00 +1300 (+13)",
	 102  		},
	 103  	}
	 104  
	 105  	for _, test := range tests {
	 106  		z, err := time.LoadLocation(test.zone)
	 107  		if err != nil {
	 108  			t.Fatal(err)
	 109  		}
	 110  		s := time.Unix(test.unix, 0).In(z).Format(format)
	 111  		if s != test.want1 {
	 112  			t.Errorf("for %s %d got %q want %q", test.zone, test.unix, s, test.want1)
	 113  		}
	 114  		s = time.Unix(test.unix+1, 0).In(z).Format(format)
	 115  		if s != test.want2 {
	 116  			t.Errorf("for %s %d got %q want %q", test.zone, test.unix, s, test.want2)
	 117  		}
	 118  	}
	 119  }
	 120  
	 121  func TestLocationNames(t *testing.T) {
	 122  	if time.Local.String() != "Local" {
	 123  		t.Errorf(`invalid Local location name: got %q want "Local"`, time.Local)
	 124  	}
	 125  	if time.UTC.String() != "UTC" {
	 126  		t.Errorf(`invalid UTC location name: got %q want "UTC"`, time.UTC)
	 127  	}
	 128  }
	 129  
	 130  func TestLoadLocationFromTZData(t *testing.T) {
	 131  	time.ForceZipFileForTesting(true)
	 132  	defer time.ForceZipFileForTesting(false)
	 133  
	 134  	const locationName = "Asia/Jerusalem"
	 135  	reference, err := time.LoadLocation(locationName)
	 136  	if err != nil {
	 137  		t.Fatal(err)
	 138  	}
	 139  
	 140  	tzinfo, err := time.LoadTzinfo(locationName, time.OrigZoneSources[len(time.OrigZoneSources)-1])
	 141  	if err != nil {
	 142  		t.Fatal(err)
	 143  	}
	 144  	sample, err := time.LoadLocationFromTZData(locationName, tzinfo)
	 145  	if err != nil {
	 146  		t.Fatal(err)
	 147  	}
	 148  
	 149  	if !reflect.DeepEqual(reference, sample) {
	 150  		t.Errorf("return values of LoadLocationFromTZData and LoadLocation don't match")
	 151  	}
	 152  }
	 153  
	 154  // Issue 30099.
	 155  func TestEarlyLocation(t *testing.T) {
	 156  	time.ForceZipFileForTesting(true)
	 157  	defer time.ForceZipFileForTesting(false)
	 158  
	 159  	const locName = "America/New_York"
	 160  	loc, err := time.LoadLocation(locName)
	 161  	if err != nil {
	 162  		t.Fatal(err)
	 163  	}
	 164  
	 165  	d := time.Date(1900, time.January, 1, 0, 0, 0, 0, loc)
	 166  	tzName, tzOffset := d.Zone()
	 167  	if want := "EST"; tzName != want {
	 168  		t.Errorf("Zone name == %s, want %s", tzName, want)
	 169  	}
	 170  	if want := -18000; tzOffset != want {
	 171  		t.Errorf("Zone offset == %d, want %d", tzOffset, want)
	 172  	}
	 173  }
	 174  
	 175  func TestMalformedTZData(t *testing.T) {
	 176  	// The goal here is just that malformed tzdata results in an error, not a panic.
	 177  	issue29437 := "TZif\x00000000000000000\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0000"
	 178  	_, err := time.LoadLocationFromTZData("abc", []byte(issue29437))
	 179  	if err == nil {
	 180  		t.Error("expected error, got none")
	 181  	}
	 182  }
	 183  
	 184  var slimTests = []struct {
	 185  	zoneName	 string
	 186  	fileName	 string
	 187  	date			 func(*time.Location) time.Time
	 188  	wantName	 string
	 189  	wantOffset int
	 190  }{
	 191  	{
	 192  		// 2020b slim tzdata for Europe/Berlin.
	 193  		zoneName:	 "Europe/Berlin",
	 194  		fileName:	 "2020b_Europe_Berlin",
	 195  		date:			 func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
	 196  		wantName:	 "CET",
	 197  		wantOffset: 3600,
	 198  	},
	 199  	{
	 200  		// 2021a slim tzdata for America/Nuuk.
	 201  		zoneName:	 "America/Nuuk",
	 202  		fileName:	 "2021a_America_Nuuk",
	 203  		date:			 func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
	 204  		wantName:	 "-03",
	 205  		wantOffset: -10800,
	 206  	},
	 207  	{
	 208  		// 2021a slim tzdata for Asia/Gaza.
	 209  		zoneName:	 "Asia/Gaza",
	 210  		fileName:	 "2021a_Asia_Gaza",
	 211  		date:			 func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
	 212  		wantName:	 "EET",
	 213  		wantOffset: 7200,
	 214  	},
	 215  	{
	 216  		// 2021a slim tzdata for Europe/Dublin.
	 217  		zoneName:	 "Europe/Dublin",
	 218  		fileName:	 "2021a_Europe_Dublin",
	 219  		date:			 func(loc *time.Location) time.Time { return time.Date(2021, time.April, 2, 11, 12, 13, 0, loc) },
	 220  		wantName:	 "IST",
	 221  		wantOffset: 3600,
	 222  	},
	 223  }
	 224  
	 225  func TestLoadLocationFromTZDataSlim(t *testing.T) {
	 226  	for _, test := range slimTests {
	 227  		tzData, err := os.ReadFile("testdata/" + test.fileName)
	 228  		if err != nil {
	 229  			t.Error(err)
	 230  			continue
	 231  		}
	 232  		reference, err := time.LoadLocationFromTZData(test.zoneName, tzData)
	 233  		if err != nil {
	 234  			t.Error(err)
	 235  			continue
	 236  		}
	 237  
	 238  		d := test.date(reference)
	 239  		tzName, tzOffset := d.Zone()
	 240  		if tzName != test.wantName {
	 241  			t.Errorf("Zone name == %s, want %s", tzName, test.wantName)
	 242  		}
	 243  		if tzOffset != test.wantOffset {
	 244  			t.Errorf("Zone offset == %d, want %d", tzOffset, test.wantOffset)
	 245  		}
	 246  	}
	 247  }
	 248  
	 249  func TestTzset(t *testing.T) {
	 250  	for _, test := range []struct {
	 251  		inStr string
	 252  		inEnd int64
	 253  		inSec int64
	 254  		name	string
	 255  		off	 int
	 256  		start int64
	 257  		end	 int64
	 258  		isDST bool
	 259  		ok		bool
	 260  	}{
	 261  		{"", 0, 0, "", 0, 0, 0, false, false},
	 262  		{"PST8PDT,M3.2.0,M11.1.0", 0, 2159200800, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
	 263  		{"PST8PDT,M3.2.0,M11.1.0", 0, 2152173599, "PST", -8 * 60 * 60, 2145916800, 2152173600, false, true},
	 264  		{"PST8PDT,M3.2.0,M11.1.0", 0, 2152173600, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
	 265  		{"PST8PDT,M3.2.0,M11.1.0", 0, 2152173601, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
	 266  		{"PST8PDT,M3.2.0,M11.1.0", 0, 2172733199, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
	 267  		{"PST8PDT,M3.2.0,M11.1.0", 0, 2172733200, "PST", -8 * 60 * 60, 2172733200, 2177452800, false, true},
	 268  		{"PST8PDT,M3.2.0,M11.1.0", 0, 2172733201, "PST", -8 * 60 * 60, 2172733200, 2177452800, false, true},
	 269  	} {
	 270  		name, off, start, end, isDST, ok := time.Tzset(test.inStr, test.inEnd, test.inSec)
	 271  		if name != test.name || off != test.off || start != test.start || end != test.end || isDST != test.isDST || ok != test.ok {
	 272  			t.Errorf("tzset(%q, %d, %d) = %q, %d, %d, %d, %t, %t, want %q, %d, %d, %d, %t, %t", test.inStr, test.inEnd, test.inSec, name, off, start, end, isDST, ok, test.name, test.off, test.start, test.end, test.isDST, test.ok)
	 273  		}
	 274  	}
	 275  }
	 276  
	 277  func TestTzsetName(t *testing.T) {
	 278  	for _, test := range []struct {
	 279  		in	 string
	 280  		name string
	 281  		out	string
	 282  		ok	 bool
	 283  	}{
	 284  		{"", "", "", false},
	 285  		{"X", "", "", false},
	 286  		{"PST", "PST", "", true},
	 287  		{"PST8PDT", "PST", "8PDT", true},
	 288  		{"PST-08", "PST", "-08", true},
	 289  		{"<A+B>+08", "A+B", "+08", true},
	 290  	} {
	 291  		name, out, ok := time.TzsetName(test.in)
	 292  		if name != test.name || out != test.out || ok != test.ok {
	 293  			t.Errorf("tzsetName(%q) = %q, %q, %t, want %q, %q, %t", test.in, name, out, ok, test.name, test.out, test.ok)
	 294  		}
	 295  	}
	 296  }
	 297  
	 298  func TestTzsetOffset(t *testing.T) {
	 299  	for _, test := range []struct {
	 300  		in	string
	 301  		off int
	 302  		out string
	 303  		ok	bool
	 304  	}{
	 305  		{"", 0, "", false},
	 306  		{"X", 0, "", false},
	 307  		{"+", 0, "", false},
	 308  		{"+08", 8 * 60 * 60, "", true},
	 309  		{"-01:02:03", -1*60*60 - 2*60 - 3, "", true},
	 310  		{"01", 1 * 60 * 60, "", true},
	 311  		{"100", 100 * 60 * 60, "", true},
	 312  		{"1000", 0, "", false},
	 313  		{"8PDT", 8 * 60 * 60, "PDT", true},
	 314  	} {
	 315  		off, out, ok := time.TzsetOffset(test.in)
	 316  		if off != test.off || out != test.out || ok != test.ok {
	 317  			t.Errorf("tzsetName(%q) = %d, %q, %t, want %d, %q, %t", test.in, off, out, ok, test.off, test.out, test.ok)
	 318  		}
	 319  	}
	 320  }
	 321  
	 322  func TestTzsetRule(t *testing.T) {
	 323  	for _, test := range []struct {
	 324  		in	string
	 325  		r	 time.Rule
	 326  		out string
	 327  		ok	bool
	 328  	}{
	 329  		{"", time.Rule{}, "", false},
	 330  		{"X", time.Rule{}, "", false},
	 331  		{"J10", time.Rule{Kind: time.RuleJulian, Day: 10, Time: 2 * 60 * 60}, "", true},
	 332  		{"20", time.Rule{Kind: time.RuleDOY, Day: 20, Time: 2 * 60 * 60}, "", true},
	 333  		{"M1.2.3", time.Rule{Kind: time.RuleMonthWeekDay, Mon: 1, Week: 2, Day: 3, Time: 2 * 60 * 60}, "", true},
	 334  		{"30/03:00:00", time.Rule{Kind: time.RuleDOY, Day: 30, Time: 3 * 60 * 60}, "", true},
	 335  		{"M4.5.6/03:00:00", time.Rule{Kind: time.RuleMonthWeekDay, Mon: 4, Week: 5, Day: 6, Time: 3 * 60 * 60}, "", true},
	 336  		{"M4.5.7/03:00:00", time.Rule{}, "", false},
	 337  		{"M4.5.6/-04", time.Rule{Kind: time.RuleMonthWeekDay, Mon: 4, Week: 5, Day: 6, Time: -4 * 60 * 60}, "", true},
	 338  	} {
	 339  		r, out, ok := time.TzsetRule(test.in)
	 340  		if r != test.r || out != test.out || ok != test.ok {
	 341  			t.Errorf("tzsetName(%q) = %#v, %q, %t, want %#v, %q, %t", test.in, r, out, ok, test.r, test.out, test.ok)
	 342  		}
	 343  	}
	 344  }
	 345  

View as plain text