github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/time/format_test.go (about)

     1  // Copyright 2009 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  	"bytes"
     9  	"fmt"
    10  	"math"
    11  	"strconv"
    12  	"strings"
    13  	"testing"
    14  	"testing/quick"
    15  	. "time"
    16  )
    17  
    18  var nextStdChunkTests = []string{
    19  	"(2006)-(01)-(02)T(15):(04):(05)(Z07:00)",
    20  	"(2006)-(01)-(02) (002) (15):(04):(05)",
    21  	"(2006)-(01) (002) (15):(04):(05)",
    22  	"(2006)-(002) (15):(04):(05)",
    23  	"(2006)(002)(01) (15):(04):(05)",
    24  	"(2006)(002)(04) (15):(04):(05)",
    25  }
    26  
    27  func TestNextStdChunk(t *testing.T) {
    28  	// Most bugs in Parse or Format boil down to problems with
    29  	// the exact detection of format chunk boundaries in the
    30  	// helper function nextStdChunk (here called as NextStdChunk).
    31  	// This test checks nextStdChunk's behavior directly,
    32  	// instead of needing to test it only indirectly through Parse/Format.
    33  
    34  	// markChunks returns format with each detected
    35  	// 'format chunk' parenthesized.
    36  	// For example showChunks("2006-01-02") == "(2006)-(01)-(02)".
    37  	markChunks := func(format string) string {
    38  		// Note that NextStdChunk and StdChunkNames
    39  		// are not part of time's public API.
    40  		// They are exported in export_test for this test.
    41  		out := ""
    42  		for s := format; s != ""; {
    43  			prefix, std, suffix := NextStdChunk(s)
    44  			out += prefix
    45  			if std > 0 {
    46  				out += "(" + StdChunkNames[std] + ")"
    47  			}
    48  			s = suffix
    49  		}
    50  		return out
    51  	}
    52  
    53  	noParens := func(r rune) rune {
    54  		if r == '(' || r == ')' {
    55  			return -1
    56  		}
    57  		return r
    58  	}
    59  
    60  	for _, marked := range nextStdChunkTests {
    61  		// marked is an expected output from markChunks.
    62  		// If we delete the parens and pass it through markChunks,
    63  		// we should get the original back.
    64  		format := strings.Map(noParens, marked)
    65  		out := markChunks(format)
    66  		if out != marked {
    67  			t.Errorf("nextStdChunk parses %q as %q, want %q", format, out, marked)
    68  		}
    69  	}
    70  }
    71  
    72  type TimeFormatTest struct {
    73  	time           Time
    74  	formattedValue string
    75  }
    76  
    77  var rfc3339Formats = []TimeFormatTest{
    78  	{Date(2008, 9, 17, 20, 4, 26, 0, UTC), "2008-09-17T20:04:26Z"},
    79  	{Date(1994, 9, 17, 20, 4, 26, 0, FixedZone("EST", -18000)), "1994-09-17T20:04:26-05:00"},
    80  	{Date(2000, 12, 26, 1, 15, 6, 0, FixedZone("OTO", 15600)), "2000-12-26T01:15:06+04:20"},
    81  }
    82  
    83  func TestRFC3339Conversion(t *testing.T) {
    84  	for _, f := range rfc3339Formats {
    85  		if f.time.Format(RFC3339) != f.formattedValue {
    86  			t.Error("RFC3339:")
    87  			t.Errorf("  want=%+v", f.formattedValue)
    88  			t.Errorf("  have=%+v", f.time.Format(RFC3339))
    89  		}
    90  	}
    91  }
    92  
    93  type FormatTest struct {
    94  	name   string
    95  	format string
    96  	result string
    97  }
    98  
    99  var formatTests = []FormatTest{
   100  	{"ANSIC", ANSIC, "Wed Feb  4 21:00:57 2009"},
   101  	{"UnixDate", UnixDate, "Wed Feb  4 21:00:57 PST 2009"},
   102  	{"RubyDate", RubyDate, "Wed Feb 04 21:00:57 -0800 2009"},
   103  	{"RFC822", RFC822, "04 Feb 09 21:00 PST"},
   104  	{"RFC850", RFC850, "Wednesday, 04-Feb-09 21:00:57 PST"},
   105  	{"RFC1123", RFC1123, "Wed, 04 Feb 2009 21:00:57 PST"},
   106  	{"RFC1123Z", RFC1123Z, "Wed, 04 Feb 2009 21:00:57 -0800"},
   107  	{"RFC3339", RFC3339, "2009-02-04T21:00:57-08:00"},
   108  	{"RFC3339Nano", RFC3339Nano, "2009-02-04T21:00:57.0123456-08:00"},
   109  	{"Kitchen", Kitchen, "9:00PM"},
   110  	{"am/pm", "3pm", "9pm"},
   111  	{"AM/PM", "3PM", "9PM"},
   112  	{"two-digit year", "06 01 02", "09 02 04"},
   113  	// Three-letter months and days must not be followed by lower-case letter.
   114  	{"Janet", "Hi Janet, the Month is January", "Hi Janet, the Month is February"},
   115  	// Time stamps, Fractional seconds.
   116  	{"Stamp", Stamp, "Feb  4 21:00:57"},
   117  	{"StampMilli", StampMilli, "Feb  4 21:00:57.012"},
   118  	{"StampMicro", StampMicro, "Feb  4 21:00:57.012345"},
   119  	{"StampNano", StampNano, "Feb  4 21:00:57.012345600"},
   120  	{"DateTime", DateTime, "2009-02-04 21:00:57"},
   121  	{"DateOnly", DateOnly, "2009-02-04"},
   122  	{"TimeOnly", TimeOnly, "21:00:57"},
   123  	{"YearDay", "Jan  2 002 __2 2", "Feb  4 035  35 4"},
   124  	{"Year", "2006 6 06 _6 __6 ___6", "2009 6 09 _6 __6 ___6"},
   125  	{"Month", "Jan January 1 01 _1", "Feb February 2 02 _2"},
   126  	{"DayOfMonth", "2 02 _2 __2", "4 04  4  35"},
   127  	{"DayOfWeek", "Mon Monday", "Wed Wednesday"},
   128  	{"Hour", "15 3 03 _3", "21 9 09 _9"},
   129  	{"Minute", "4 04 _4", "0 00 _0"},
   130  	{"Second", "5 05 _5", "57 57 _57"},
   131  }
   132  
   133  func TestFormat(t *testing.T) {
   134  	// The numeric time represents Thu Feb  4 21:00:57.012345600 PST 2009
   135  	time := Unix(0, 1233810057012345600)
   136  	for _, test := range formatTests {
   137  		result := time.Format(test.format)
   138  		if result != test.result {
   139  			t.Errorf("%s expected %q got %q", test.name, test.result, result)
   140  		}
   141  	}
   142  }
   143  
   144  var goStringTests = []struct {
   145  	in   Time
   146  	want string
   147  }{
   148  	{Date(2009, February, 5, 5, 0, 57, 12345600, UTC),
   149  		"time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.UTC)"},
   150  	{Date(2009, February, 5, 5, 0, 57, 12345600, Local),
   151  		"time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Local)"},
   152  	{Date(2009, February, 5, 5, 0, 57, 12345600, FixedZone("Europe/Berlin", 3*60*60)),
   153  		`time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Location("Europe/Berlin"))`,
   154  	},
   155  	{Date(2009, February, 5, 5, 0, 57, 12345600, FixedZone("Non-ASCII character ⏰", 3*60*60)),
   156  		`time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Location("Non-ASCII character \xe2\x8f\xb0"))`,
   157  	},
   158  }
   159  
   160  func TestGoString(t *testing.T) {
   161  	// The numeric time represents Thu Feb  4 21:00:57.012345600 PST 2009
   162  	for _, tt := range goStringTests {
   163  		if tt.in.GoString() != tt.want {
   164  			t.Errorf("GoString (%q): got %q want %q", tt.in, tt.in.GoString(), tt.want)
   165  		}
   166  	}
   167  }
   168  
   169  // issue 12440.
   170  func TestFormatSingleDigits(t *testing.T) {
   171  	time := Date(2001, 2, 3, 4, 5, 6, 700000000, UTC)
   172  	test := FormatTest{"single digit format", "3:4:5", "4:5:6"}
   173  	result := time.Format(test.format)
   174  	if result != test.result {
   175  		t.Errorf("%s expected %q got %q", test.name, test.result, result)
   176  	}
   177  }
   178  
   179  func TestFormatShortYear(t *testing.T) {
   180  	years := []int{
   181  		-100001, -100000, -99999,
   182  		-10001, -10000, -9999,
   183  		-1001, -1000, -999,
   184  		-101, -100, -99,
   185  		-11, -10, -9,
   186  		-1, 0, 1,
   187  		9, 10, 11,
   188  		99, 100, 101,
   189  		999, 1000, 1001,
   190  		9999, 10000, 10001,
   191  		99999, 100000, 100001,
   192  	}
   193  
   194  	for _, y := range years {
   195  		time := Date(y, January, 1, 0, 0, 0, 0, UTC)
   196  		result := time.Format("2006.01.02")
   197  		var want string
   198  		if y < 0 {
   199  			// The 4 in %04d counts the - sign, so print -y instead
   200  			// and introduce our own - sign.
   201  			want = fmt.Sprintf("-%04d.%02d.%02d", -y, 1, 1)
   202  		} else {
   203  			want = fmt.Sprintf("%04d.%02d.%02d", y, 1, 1)
   204  		}
   205  		if result != want {
   206  			t.Errorf("(jan 1 %d).Format(\"2006.01.02\") = %q, want %q", y, result, want)
   207  		}
   208  	}
   209  }
   210  
   211  type ParseTest struct {
   212  	name       string
   213  	format     string
   214  	value      string
   215  	hasTZ      bool // contains a time zone
   216  	hasWD      bool // contains a weekday
   217  	yearSign   int  // sign of year, -1 indicates the year is not present in the format
   218  	fracDigits int  // number of digits of fractional second
   219  }
   220  
   221  var parseTests = []ParseTest{
   222  	{"ANSIC", ANSIC, "Thu Feb  4 21:00:57 2010", false, true, 1, 0},
   223  	{"UnixDate", UnixDate, "Thu Feb  4 21:00:57 PST 2010", true, true, 1, 0},
   224  	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
   225  	{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57 PST", true, true, 1, 0},
   226  	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true, 1, 0},
   227  	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 22:00:57 PDT", true, true, 1, 0},
   228  	{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57 -0800", true, true, 1, 0},
   229  	{"RFC3339", RFC3339, "2010-02-04T21:00:57-08:00", true, false, 1, 0},
   230  	{"custom: \"2006-01-02 15:04:05-07\"", "2006-01-02 15:04:05-07", "2010-02-04 21:00:57-08", true, false, 1, 0},
   231  	// Optional fractional seconds.
   232  	{"ANSIC", ANSIC, "Thu Feb  4 21:00:57.0 2010", false, true, 1, 1},
   233  	{"UnixDate", UnixDate, "Thu Feb  4 21:00:57.01 PST 2010", true, true, 1, 2},
   234  	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57.012 -0800 2010", true, true, 1, 3},
   235  	{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57.0123 PST", true, true, 1, 4},
   236  	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57.01234 PST", true, true, 1, 5},
   237  	{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57.01234 -0800", true, true, 1, 5},
   238  	{"RFC3339", RFC3339, "2010-02-04T21:00:57.012345678-08:00", true, false, 1, 9},
   239  	{"custom: \"2006-01-02 15:04:05\"", "2006-01-02 15:04:05", "2010-02-04 21:00:57.0", false, false, 1, 0},
   240  	// Amount of white space should not matter.
   241  	{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
   242  	{"ANSIC", ANSIC, "Thu      Feb     4     21:00:57     2010", false, true, 1, 0},
   243  	// Case should not matter
   244  	{"ANSIC", ANSIC, "THU FEB 4 21:00:57 2010", false, true, 1, 0},
   245  	{"ANSIC", ANSIC, "thu feb 4 21:00:57 2010", false, true, 1, 0},
   246  	// Fractional seconds.
   247  	{"millisecond:: dot separator", "Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 21:00:57.012 2010", false, true, 1, 3},
   248  	{"microsecond:: dot separator", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb  4 21:00:57.012345 2010", false, true, 1, 6},
   249  	{"nanosecond:: dot separator", "Mon Jan _2 15:04:05.000000000 2006", "Thu Feb  4 21:00:57.012345678 2010", false, true, 1, 9},
   250  	{"millisecond:: comma separator", "Mon Jan _2 15:04:05,000 2006", "Thu Feb  4 21:00:57.012 2010", false, true, 1, 3},
   251  	{"microsecond:: comma separator", "Mon Jan _2 15:04:05,000000 2006", "Thu Feb  4 21:00:57.012345 2010", false, true, 1, 6},
   252  	{"nanosecond:: comma separator", "Mon Jan _2 15:04:05,000000000 2006", "Thu Feb  4 21:00:57.012345678 2010", false, true, 1, 9},
   253  
   254  	// Leading zeros in other places should not be taken as fractional seconds.
   255  	{"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1},
   256  	{"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2},
   257  	// Month and day names only match when not followed by a lower-case letter.
   258  	{"Janet", "Hi Janet, the Month is January: Jan _2 15:04:05 2006", "Hi Janet, the Month is February: Feb  4 21:00:57 2010", false, true, 1, 0},
   259  
   260  	// GMT with offset.
   261  	{"GMT-8", UnixDate, "Fri Feb  5 05:00:57 GMT-8 2010", true, true, 1, 0},
   262  
   263  	// Accept any number of fractional second digits (including none) for .999...
   264  	// In Go 1, .999... was completely ignored in the format, meaning the first two
   265  	// cases would succeed, but the next four would not. Go 1.1 accepts all six.
   266  	// decimal "." separator.
   267  	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
   268  	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
   269  	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
   270  	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
   271  	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
   272  	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
   273  	// comma "," separator.
   274  	{"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
   275  	{"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
   276  	{"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
   277  	{"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
   278  	{"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
   279  	{"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
   280  
   281  	// issue 4502.
   282  	{"", StampNano, "Feb  4 21:00:57.012345678", false, false, -1, 9},
   283  	{"", "Jan _2 15:04:05.999", "Feb  4 21:00:57.012300000", false, false, -1, 4},
   284  	{"", "Jan _2 15:04:05.999", "Feb  4 21:00:57.012345678", false, false, -1, 9},
   285  	{"", "Jan _2 15:04:05.999999999", "Feb  4 21:00:57.0123", false, false, -1, 4},
   286  	{"", "Jan _2 15:04:05.999999999", "Feb  4 21:00:57.012345678", false, false, -1, 9},
   287  
   288  	// Day of year.
   289  	{"", "2006-01-02 002 15:04:05", "2010-02-04 035 21:00:57", false, false, 1, 0},
   290  	{"", "2006-01 002 15:04:05", "2010-02 035 21:00:57", false, false, 1, 0},
   291  	{"", "2006-002 15:04:05", "2010-035 21:00:57", false, false, 1, 0},
   292  	{"", "200600201 15:04:05", "201003502 21:00:57", false, false, 1, 0},
   293  	{"", "200600204 15:04:05", "201003504 21:00:57", false, false, 1, 0},
   294  }
   295  
   296  func TestParse(t *testing.T) {
   297  	for _, test := range parseTests {
   298  		time, err := Parse(test.format, test.value)
   299  		if err != nil {
   300  			t.Errorf("%s error: %v", test.name, err)
   301  		} else {
   302  			checkTime(time, &test, t)
   303  		}
   304  	}
   305  }
   306  
   307  // All parsed with ANSIC.
   308  var dayOutOfRangeTests = []struct {
   309  	date string
   310  	ok   bool
   311  }{
   312  	{"Thu Jan 99 21:00:57 2010", false},
   313  	{"Thu Jan 31 21:00:57 2010", true},
   314  	{"Thu Jan 32 21:00:57 2010", false},
   315  	{"Thu Feb 28 21:00:57 2012", true},
   316  	{"Thu Feb 29 21:00:57 2012", true},
   317  	{"Thu Feb 29 21:00:57 2010", false},
   318  	{"Thu Mar 31 21:00:57 2010", true},
   319  	{"Thu Mar 32 21:00:57 2010", false},
   320  	{"Thu Apr 30 21:00:57 2010", true},
   321  	{"Thu Apr 31 21:00:57 2010", false},
   322  	{"Thu May 31 21:00:57 2010", true},
   323  	{"Thu May 32 21:00:57 2010", false},
   324  	{"Thu Jun 30 21:00:57 2010", true},
   325  	{"Thu Jun 31 21:00:57 2010", false},
   326  	{"Thu Jul 31 21:00:57 2010", true},
   327  	{"Thu Jul 32 21:00:57 2010", false},
   328  	{"Thu Aug 31 21:00:57 2010", true},
   329  	{"Thu Aug 32 21:00:57 2010", false},
   330  	{"Thu Sep 30 21:00:57 2010", true},
   331  	{"Thu Sep 31 21:00:57 2010", false},
   332  	{"Thu Oct 31 21:00:57 2010", true},
   333  	{"Thu Oct 32 21:00:57 2010", false},
   334  	{"Thu Nov 30 21:00:57 2010", true},
   335  	{"Thu Nov 31 21:00:57 2010", false},
   336  	{"Thu Dec 31 21:00:57 2010", true},
   337  	{"Thu Dec 32 21:00:57 2010", false},
   338  	{"Thu Dec 00 21:00:57 2010", false},
   339  }
   340  
   341  func TestParseDayOutOfRange(t *testing.T) {
   342  	for _, test := range dayOutOfRangeTests {
   343  		_, err := Parse(ANSIC, test.date)
   344  		switch {
   345  		case test.ok && err == nil:
   346  			// OK
   347  		case !test.ok && err != nil:
   348  			if !strings.Contains(err.Error(), "day out of range") {
   349  				t.Errorf("%q: expected 'day' error, got %v", test.date, err)
   350  			}
   351  		case test.ok && err != nil:
   352  			t.Errorf("%q: unexpected error: %v", test.date, err)
   353  		case !test.ok && err == nil:
   354  			t.Errorf("%q: expected 'day' error, got none", test.date)
   355  		}
   356  	}
   357  }
   358  
   359  // TestParseInLocation checks that the Parse and ParseInLocation
   360  // functions do not get confused by the fact that AST (Arabia Standard
   361  // Time) and AST (Atlantic Standard Time) are different time zones,
   362  // even though they have the same abbreviation.
   363  //
   364  // ICANN has been slowly phasing out invented abbreviation in favor of
   365  // numeric time zones (for example, the Asia/Baghdad time zone
   366  // abbreviation got changed from AST to +03 in the 2017a tzdata
   367  // release); but we still want to make sure that the time package does
   368  // not get confused on systems with slightly older tzdata packages.
   369  func TestParseInLocation(t *testing.T) {
   370  
   371  	baghdad, err := LoadLocation("Asia/Baghdad")
   372  	if err != nil {
   373  		t.Fatal(err)
   374  	}
   375  
   376  	var t1, t2 Time
   377  
   378  	t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad)
   379  	if err != nil {
   380  		t.Fatal(err)
   381  	}
   382  
   383  	_, offset := t1.Zone()
   384  
   385  	// A zero offset means that ParseInLocation did not recognize the
   386  	// 'AST' abbreviation as matching the current location (Baghdad,
   387  	// where we'd expect a +03 hrs offset); likely because we're using
   388  	// a recent tzdata release (2017a or newer).
   389  	// If it happens, skip the Baghdad test.
   390  	if offset != 0 {
   391  		t2 = Date(2013, February, 1, 00, 00, 00, 0, baghdad)
   392  		if t1 != t2 {
   393  			t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2)
   394  		}
   395  		if offset != 3*60*60 {
   396  			t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60)
   397  		}
   398  	}
   399  
   400  	blancSablon, err := LoadLocation("America/Blanc-Sablon")
   401  	if err != nil {
   402  		t.Fatal(err)
   403  	}
   404  
   405  	// In this case 'AST' means 'Atlantic Standard Time', and we
   406  	// expect the abbreviation to correctly match the american
   407  	// location.
   408  	t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", blancSablon)
   409  	if err != nil {
   410  		t.Fatal(err)
   411  	}
   412  	t2 = Date(2013, February, 1, 00, 00, 00, 0, blancSablon)
   413  	if t1 != t2 {
   414  		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon) = %v, want %v", t1, t2)
   415  	}
   416  	_, offset = t1.Zone()
   417  	if offset != -4*60*60 {
   418  		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon).Zone = _, %d, want _, %d", offset, -4*60*60)
   419  	}
   420  }
   421  
   422  func TestLoadLocationZipFile(t *testing.T) {
   423  	undo := DisablePlatformSources()
   424  	defer undo()
   425  
   426  	_, err := LoadLocation("Australia/Sydney")
   427  	if err != nil {
   428  		t.Fatal(err)
   429  	}
   430  }
   431  
   432  var rubyTests = []ParseTest{
   433  	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
   434  	// Ignore the time zone in the test. If it parses, it'll be OK.
   435  	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0000 2010", false, true, 1, 0},
   436  	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 +0000 2010", false, true, 1, 0},
   437  	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 +1130 2010", false, true, 1, 0},
   438  }
   439  
   440  // Problematic time zone format needs special tests.
   441  func TestRubyParse(t *testing.T) {
   442  	for _, test := range rubyTests {
   443  		time, err := Parse(test.format, test.value)
   444  		if err != nil {
   445  			t.Errorf("%s error: %v", test.name, err)
   446  		} else {
   447  			checkTime(time, &test, t)
   448  		}
   449  	}
   450  }
   451  
   452  func checkTime(time Time, test *ParseTest, t *testing.T) {
   453  	// The time should be Thu Feb  4 21:00:57 PST 2010
   454  	if test.yearSign >= 0 && test.yearSign*time.Year() != 2010 {
   455  		t.Errorf("%s: bad year: %d not %d", test.name, time.Year(), 2010)
   456  	}
   457  	if time.Month() != February {
   458  		t.Errorf("%s: bad month: %s not %s", test.name, time.Month(), February)
   459  	}
   460  	if time.Day() != 4 {
   461  		t.Errorf("%s: bad day: %d not %d", test.name, time.Day(), 4)
   462  	}
   463  	if time.Hour() != 21 {
   464  		t.Errorf("%s: bad hour: %d not %d", test.name, time.Hour(), 21)
   465  	}
   466  	if time.Minute() != 0 {
   467  		t.Errorf("%s: bad minute: %d not %d", test.name, time.Minute(), 0)
   468  	}
   469  	if time.Second() != 57 {
   470  		t.Errorf("%s: bad second: %d not %d", test.name, time.Second(), 57)
   471  	}
   472  	// Nanoseconds must be checked against the precision of the input.
   473  	nanosec, err := strconv.ParseUint("012345678"[:test.fracDigits]+"000000000"[:9-test.fracDigits], 10, 0)
   474  	if err != nil {
   475  		panic(err)
   476  	}
   477  	if time.Nanosecond() != int(nanosec) {
   478  		t.Errorf("%s: bad nanosecond: %d not %d", test.name, time.Nanosecond(), nanosec)
   479  	}
   480  	name, offset := time.Zone()
   481  	if test.hasTZ && offset != -28800 {
   482  		t.Errorf("%s: bad tz offset: %s %d not %d", test.name, name, offset, -28800)
   483  	}
   484  	if test.hasWD && time.Weekday() != Thursday {
   485  		t.Errorf("%s: bad weekday: %s not %s", test.name, time.Weekday(), Thursday)
   486  	}
   487  }
   488  
   489  func TestFormatAndParse(t *testing.T) {
   490  	const fmt = "Mon MST " + RFC3339 // all fields
   491  	f := func(sec int64) bool {
   492  		t1 := Unix(sec/2, 0)
   493  		if t1.Year() < 1000 || t1.Year() > 9999 || t1.Unix() != sec {
   494  			// not required to work
   495  			return true
   496  		}
   497  		t2, err := Parse(fmt, t1.Format(fmt))
   498  		if err != nil {
   499  			t.Errorf("error: %s", err)
   500  			return false
   501  		}
   502  		if t1.Unix() != t2.Unix() || t1.Nanosecond() != t2.Nanosecond() {
   503  			t.Errorf("FormatAndParse %d: %q(%d) %q(%d)", sec, t1, t1.Unix(), t2, t2.Unix())
   504  			return false
   505  		}
   506  		return true
   507  	}
   508  	f32 := func(sec int32) bool { return f(int64(sec)) }
   509  	cfg := &quick.Config{MaxCount: 10000}
   510  
   511  	// Try a reasonable date first, then the huge ones.
   512  	if err := quick.Check(f32, cfg); err != nil {
   513  		t.Fatal(err)
   514  	}
   515  	if err := quick.Check(f, cfg); err != nil {
   516  		t.Fatal(err)
   517  	}
   518  }
   519  
   520  type ParseTimeZoneTest struct {
   521  	value  string
   522  	length int
   523  	ok     bool
   524  }
   525  
   526  var parseTimeZoneTests = []ParseTimeZoneTest{
   527  	{"gmt hi there", 0, false},
   528  	{"GMT hi there", 3, true},
   529  	{"GMT+12 hi there", 6, true},
   530  	{"GMT+00 hi there", 6, true},
   531  	{"GMT+", 3, true},
   532  	{"GMT+3", 5, true},
   533  	{"GMT+a", 3, true},
   534  	{"GMT+3a", 5, true},
   535  	{"GMT-5 hi there", 5, true},
   536  	{"GMT-51 hi there", 3, true},
   537  	{"ChST hi there", 4, true},
   538  	{"MeST hi there", 4, true},
   539  	{"MSDx", 3, true},
   540  	{"MSDY", 0, false}, // four letters must end in T.
   541  	{"ESAST hi", 5, true},
   542  	{"ESASTT hi", 0, false}, // run of upper-case letters too long.
   543  	{"ESATY hi", 0, false},  // five letters must end in T.
   544  	{"WITA hi", 4, true},    // Issue #18251
   545  	// Issue #24071
   546  	{"+03 hi", 3, true},
   547  	{"-04 hi", 3, true},
   548  	// Issue #26032
   549  	{"+00", 3, true},
   550  	{"-11", 3, true},
   551  	{"-12", 3, true},
   552  	{"-23", 3, true},
   553  	{"-24", 0, false},
   554  	{"+13", 3, true},
   555  	{"+14", 3, true},
   556  	{"+23", 3, true},
   557  	{"+24", 0, false},
   558  }
   559  
   560  func TestParseTimeZone(t *testing.T) {
   561  	for _, test := range parseTimeZoneTests {
   562  		length, ok := ParseTimeZone(test.value)
   563  		if ok != test.ok {
   564  			t.Errorf("expected %t for %q got %t", test.ok, test.value, ok)
   565  		} else if length != test.length {
   566  			t.Errorf("expected %d for %q got %d", test.length, test.value, length)
   567  		}
   568  	}
   569  }
   570  
   571  type ParseErrorTest struct {
   572  	format string
   573  	value  string
   574  	expect string // must appear within the error
   575  }
   576  
   577  var parseErrorTests = []ParseErrorTest{
   578  	{ANSIC, "Feb  4 21:00:60 2010", "cannot parse"}, // cannot parse Feb as Mon
   579  	{ANSIC, "Thu Feb  4 21:00:57 @2010", "cannot parse"},
   580  	{ANSIC, "Thu Feb  4 21:00:60 2010", "second out of range"},
   581  	{ANSIC, "Thu Feb  4 21:61:57 2010", "minute out of range"},
   582  	{ANSIC, "Thu Feb  4 24:00:60 2010", "hour out of range"},
   583  	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59x01 2010", "cannot parse"},
   584  	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59.xxx 2010", "cannot parse"},
   585  	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59.-123 2010", "fractional second out of range"},
   586  	// issue 4502. StampNano requires exactly 9 digits of precision.
   587  	{StampNano, "Dec  7 11:22:01.000000", `cannot parse ".000000" as ".000000000"`},
   588  	{StampNano, "Dec  7 11:22:01.0000000000", `extra text: "0"`},
   589  	// issue 4493. Helpful errors.
   590  	{RFC3339, "2006-01-02T15:04:05Z07:00", `parsing time "2006-01-02T15:04:05Z07:00": extra text: "07:00"`},
   591  	{RFC3339, "2006-01-02T15:04_abc", `parsing time "2006-01-02T15:04_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as ":"`},
   592  	{RFC3339, "2006-01-02T15:04:05_abc", `parsing time "2006-01-02T15:04:05_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as "Z07:00"`},
   593  	{RFC3339, "2006-01-02T15:04:05Z_abc", `parsing time "2006-01-02T15:04:05Z_abc": extra text: "_abc"`},
   594  	// invalid second followed by optional fractional seconds
   595  	{RFC3339, "2010-02-04T21:00:67.012345678-08:00", "second out of range"},
   596  	// issue 54569
   597  	{RFC3339, "0000-01-01T00:00:.0+00:00", `parsing time "0000-01-01T00:00:.0+00:00" as "2006-01-02T15:04:05Z07:00": cannot parse ".0+00:00" as "05"`},
   598  	// issue 21113
   599  	{"_2 Jan 06 15:04 MST", "4 --- 00 00:00 GMT", "cannot parse"},
   600  	{"_2 January 06 15:04 MST", "4 --- 00 00:00 GMT", "cannot parse"},
   601  
   602  	// invalid or mismatched day-of-year
   603  	{"Jan _2 002 2006", "Feb  4 034 2006", "day-of-year does not match day"},
   604  	{"Jan _2 002 2006", "Feb  4 004 2006", "day-of-year does not match month"},
   605  
   606  	// issue 45391.
   607  	{`"2006-01-02T15:04:05Z07:00"`, "0", `parsing time "0" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse "0" as "\""`},
   608  	{RFC3339, "\"", `parsing time "\"" as "2006-01-02T15:04:05Z07:00": cannot parse "\"" as "2006"`},
   609  
   610  	// issue 54570
   611  	{RFC3339, "0000-01-01T00:00:00+00:+0", `parsing time "0000-01-01T00:00:00+00:+0" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "Z07:00"`},
   612  	{RFC3339, "0000-01-01T00:00:00+-0:00", `parsing time "0000-01-01T00:00:00+-0:00" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "Z07:00"`},
   613  }
   614  
   615  func TestParseErrors(t *testing.T) {
   616  	for _, test := range parseErrorTests {
   617  		_, err := Parse(test.format, test.value)
   618  		if err == nil {
   619  			t.Errorf("expected error for %q %q", test.format, test.value)
   620  		} else if !strings.Contains(err.Error(), test.expect) {
   621  			t.Errorf("expected error with %q for %q %q; got %s", test.expect, test.format, test.value, err)
   622  		}
   623  	}
   624  }
   625  
   626  func TestNoonIs12PM(t *testing.T) {
   627  	noon := Date(0, January, 1, 12, 0, 0, 0, UTC)
   628  	const expect = "12:00PM"
   629  	got := noon.Format("3:04PM")
   630  	if got != expect {
   631  		t.Errorf("got %q; expect %q", got, expect)
   632  	}
   633  	got = noon.Format("03:04PM")
   634  	if got != expect {
   635  		t.Errorf("got %q; expect %q", got, expect)
   636  	}
   637  }
   638  
   639  func TestMidnightIs12AM(t *testing.T) {
   640  	midnight := Date(0, January, 1, 0, 0, 0, 0, UTC)
   641  	expect := "12:00AM"
   642  	got := midnight.Format("3:04PM")
   643  	if got != expect {
   644  		t.Errorf("got %q; expect %q", got, expect)
   645  	}
   646  	got = midnight.Format("03:04PM")
   647  	if got != expect {
   648  		t.Errorf("got %q; expect %q", got, expect)
   649  	}
   650  }
   651  
   652  func Test12PMIsNoon(t *testing.T) {
   653  	noon, err := Parse("3:04PM", "12:00PM")
   654  	if err != nil {
   655  		t.Fatal("error parsing date:", err)
   656  	}
   657  	if noon.Hour() != 12 {
   658  		t.Errorf("got %d; expect 12", noon.Hour())
   659  	}
   660  	noon, err = Parse("03:04PM", "12:00PM")
   661  	if err != nil {
   662  		t.Fatal("error parsing date:", err)
   663  	}
   664  	if noon.Hour() != 12 {
   665  		t.Errorf("got %d; expect 12", noon.Hour())
   666  	}
   667  }
   668  
   669  func Test12AMIsMidnight(t *testing.T) {
   670  	midnight, err := Parse("3:04PM", "12:00AM")
   671  	if err != nil {
   672  		t.Fatal("error parsing date:", err)
   673  	}
   674  	if midnight.Hour() != 0 {
   675  		t.Errorf("got %d; expect 0", midnight.Hour())
   676  	}
   677  	midnight, err = Parse("03:04PM", "12:00AM")
   678  	if err != nil {
   679  		t.Fatal("error parsing date:", err)
   680  	}
   681  	if midnight.Hour() != 0 {
   682  		t.Errorf("got %d; expect 0", midnight.Hour())
   683  	}
   684  }
   685  
   686  // Check that a time without a Zone still produces a (numeric) time zone
   687  // when formatted with MST as a requested zone.
   688  func TestMissingZone(t *testing.T) {
   689  	time, err := Parse(RubyDate, "Thu Feb 02 16:10:03 -0500 2006")
   690  	if err != nil {
   691  		t.Fatal("error parsing date:", err)
   692  	}
   693  	expect := "Thu Feb  2 16:10:03 -0500 2006" // -0500 not EST
   694  	str := time.Format(UnixDate)               // uses MST as its time zone
   695  	if str != expect {
   696  		t.Errorf("got %s; expect %s", str, expect)
   697  	}
   698  }
   699  
   700  func TestMinutesInTimeZone(t *testing.T) {
   701  	time, err := Parse(RubyDate, "Mon Jan 02 15:04:05 +0123 2006")
   702  	if err != nil {
   703  		t.Fatal("error parsing date:", err)
   704  	}
   705  	expected := (1*60 + 23) * 60
   706  	_, offset := time.Zone()
   707  	if offset != expected {
   708  		t.Errorf("ZoneOffset = %d, want %d", offset, expected)
   709  	}
   710  }
   711  
   712  type SecondsTimeZoneOffsetTest struct {
   713  	format         string
   714  	value          string
   715  	expectedoffset int
   716  }
   717  
   718  var secondsTimeZoneOffsetTests = []SecondsTimeZoneOffsetTest{
   719  	{"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
   720  	{"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02-00:34:08", -(34*60 + 8)},
   721  	{"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02+003408", 34*60 + 8},
   722  	{"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
   723  	{"2006-01-02T15:04:05Z070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
   724  	{"2006-01-02T15:04:05Z07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
   725  	{"2006-01-02T15:04:05-07", "1871-01-01T05:33:02+01", 1 * 60 * 60},
   726  	{"2006-01-02T15:04:05-07", "1871-01-01T05:33:02-02", -2 * 60 * 60},
   727  	{"2006-01-02T15:04:05Z07", "1871-01-01T05:33:02-02", -2 * 60 * 60},
   728  }
   729  
   730  func TestParseSecondsInTimeZone(t *testing.T) {
   731  	// should accept timezone offsets with seconds like: Zone America/New_York   -4:56:02 -      LMT     1883 Nov 18 12:03:58
   732  	for _, test := range secondsTimeZoneOffsetTests {
   733  		time, err := Parse(test.format, test.value)
   734  		if err != nil {
   735  			t.Fatal("error parsing date:", err)
   736  		}
   737  		_, offset := time.Zone()
   738  		if offset != test.expectedoffset {
   739  			t.Errorf("ZoneOffset = %d, want %d", offset, test.expectedoffset)
   740  		}
   741  	}
   742  }
   743  
   744  func TestFormatSecondsInTimeZone(t *testing.T) {
   745  	for _, test := range secondsTimeZoneOffsetTests {
   746  		d := Date(1871, 1, 1, 5, 33, 2, 0, FixedZone("LMT", test.expectedoffset))
   747  		timestr := d.Format(test.format)
   748  		if timestr != test.value {
   749  			t.Errorf("Format = %s, want %s", timestr, test.value)
   750  		}
   751  	}
   752  }
   753  
   754  // Issue 11334.
   755  func TestUnderscoreTwoThousand(t *testing.T) {
   756  	format := "15:04_20060102"
   757  	input := "14:38_20150618"
   758  	time, err := Parse(format, input)
   759  	if err != nil {
   760  		t.Error(err)
   761  	}
   762  	if y, m, d := time.Date(); y != 2015 || m != 6 || d != 18 {
   763  		t.Errorf("Incorrect y/m/d, got %d/%d/%d", y, m, d)
   764  	}
   765  	if h := time.Hour(); h != 14 {
   766  		t.Errorf("Incorrect hour, got %d", h)
   767  	}
   768  	if m := time.Minute(); m != 38 {
   769  		t.Errorf("Incorrect minute, got %d", m)
   770  	}
   771  }
   772  
   773  // Issue 29918, 29916
   774  func TestStd0xParseError(t *testing.T) {
   775  	tests := []struct {
   776  		format, value, valueElemPrefix string
   777  	}{
   778  		{"01 MST", "0 MST", "0"},
   779  		{"01 MST", "1 MST", "1"},
   780  		{RFC850, "Thursday, 04-Feb-1 21:00:57 PST", "1"},
   781  	}
   782  	for _, tt := range tests {
   783  		_, err := Parse(tt.format, tt.value)
   784  		if err == nil {
   785  			t.Errorf("Parse(%q, %q) did not fail as expected", tt.format, tt.value)
   786  		} else if perr, ok := err.(*ParseError); !ok {
   787  			t.Errorf("Parse(%q, %q) returned error type %T, expected ParseError", tt.format, tt.value, perr)
   788  		} else if !strings.Contains(perr.Error(), "cannot parse") || !strings.HasPrefix(perr.ValueElem, tt.valueElemPrefix) {
   789  			t.Errorf("Parse(%q, %q) returned wrong parsing error message: %v", tt.format, tt.value, perr)
   790  		}
   791  	}
   792  }
   793  
   794  var monthOutOfRangeTests = []struct {
   795  	value string
   796  	ok    bool
   797  }{
   798  	{"00-01", false},
   799  	{"13-01", false},
   800  	{"01-01", true},
   801  }
   802  
   803  func TestParseMonthOutOfRange(t *testing.T) {
   804  	for _, test := range monthOutOfRangeTests {
   805  		_, err := Parse("01-02", test.value)
   806  		switch {
   807  		case !test.ok && err != nil:
   808  			if !strings.Contains(err.Error(), "month out of range") {
   809  				t.Errorf("%q: expected 'month' error, got %v", test.value, err)
   810  			}
   811  		case test.ok && err != nil:
   812  			t.Errorf("%q: unexpected error: %v", test.value, err)
   813  		case !test.ok && err == nil:
   814  			t.Errorf("%q: expected 'month' error, got none", test.value)
   815  		}
   816  	}
   817  }
   818  
   819  // Issue 37387.
   820  func TestParseYday(t *testing.T) {
   821  	t.Parallel()
   822  	for i := 1; i <= 365; i++ {
   823  		d := fmt.Sprintf("2020-%03d", i)
   824  		tm, err := Parse("2006-002", d)
   825  		if err != nil {
   826  			t.Errorf("unexpected error for %s: %v", d, err)
   827  		} else if tm.Year() != 2020 || tm.YearDay() != i {
   828  			t.Errorf("got year %d yearday %d, want %d %d", tm.Year(), tm.YearDay(), 2020, i)
   829  		}
   830  	}
   831  }
   832  
   833  // Issue 45391.
   834  func TestQuote(t *testing.T) {
   835  	tests := []struct {
   836  		s, want string
   837  	}{
   838  		{`"`, `"\""`},
   839  		{`abc"xyz"`, `"abc\"xyz\""`},
   840  		{"", `""`},
   841  		{"abc", `"abc"`},
   842  		{`☺`, `"\xe2\x98\xba"`},
   843  		{`☺ hello ☺ hello`, `"\xe2\x98\xba hello \xe2\x98\xba hello"`},
   844  		{"\x04", `"\x04"`},
   845  	}
   846  	for _, tt := range tests {
   847  		if q := Quote(tt.s); q != tt.want {
   848  			t.Errorf("Quote(%q) = got %q, want %q", tt.s, q, tt.want)
   849  		}
   850  	}
   851  
   852  }
   853  
   854  // Issue 48037
   855  func TestFormatFractionalSecondSeparators(t *testing.T) {
   856  	tests := []struct {
   857  		s, want string
   858  	}{
   859  		{`15:04:05.000`, `21:00:57.012`},
   860  		{`15:04:05.999`, `21:00:57.012`},
   861  		{`15:04:05,000`, `21:00:57,012`},
   862  		{`15:04:05,999`, `21:00:57,012`},
   863  	}
   864  
   865  	// The numeric time represents Thu Feb  4 21:00:57.012345600 PST 2009
   866  	time := Unix(0, 1233810057012345600)
   867  	for _, tt := range tests {
   868  		if q := time.Format(tt.s); q != tt.want {
   869  			t.Errorf("Format(%q) = got %q, want %q", tt.s, q, tt.want)
   870  		}
   871  	}
   872  }
   873  
   874  var longFractionalDigitsTests = []struct {
   875  	value string
   876  	want  int
   877  }{
   878  	// 9 digits
   879  	{"2021-09-29T16:04:33.000000000Z", 0},
   880  	{"2021-09-29T16:04:33.000000001Z", 1},
   881  	{"2021-09-29T16:04:33.100000000Z", 100_000_000},
   882  	{"2021-09-29T16:04:33.100000001Z", 100_000_001},
   883  	{"2021-09-29T16:04:33.999999999Z", 999_999_999},
   884  	{"2021-09-29T16:04:33.012345678Z", 12_345_678},
   885  	// 10 digits, truncates
   886  	{"2021-09-29T16:04:33.0000000000Z", 0},
   887  	{"2021-09-29T16:04:33.0000000001Z", 0},
   888  	{"2021-09-29T16:04:33.1000000000Z", 100_000_000},
   889  	{"2021-09-29T16:04:33.1000000009Z", 100_000_000},
   890  	{"2021-09-29T16:04:33.9999999999Z", 999_999_999},
   891  	{"2021-09-29T16:04:33.0123456789Z", 12_345_678},
   892  	// 11 digits, truncates
   893  	{"2021-09-29T16:04:33.10000000000Z", 100_000_000},
   894  	{"2021-09-29T16:04:33.00123456789Z", 1_234_567},
   895  	// 12 digits, truncates
   896  	{"2021-09-29T16:04:33.000123456789Z", 123_456},
   897  	// 15 digits, truncates
   898  	{"2021-09-29T16:04:33.9999999999999999Z", 999_999_999},
   899  }
   900  
   901  // Issue 48685 and 54567.
   902  func TestParseFractionalSecondsLongerThanNineDigits(t *testing.T) {
   903  	for _, tt := range longFractionalDigitsTests {
   904  		for _, format := range []string{RFC3339, RFC3339Nano} {
   905  			tm, err := Parse(format, tt.value)
   906  			if err != nil {
   907  				t.Errorf("Parse(%q, %q) error: %v", format, tt.value, err)
   908  				continue
   909  			}
   910  			if got := tm.Nanosecond(); got != tt.want {
   911  				t.Errorf("Parse(%q, %q) = got %d, want %d", format, tt.value, got, tt.want)
   912  			}
   913  		}
   914  	}
   915  }
   916  
   917  func FuzzFormatRFC3339(f *testing.F) {
   918  	for _, ts := range [][2]int64{
   919  		{math.MinInt64, math.MinInt64}, // 292277026304-08-26T15:42:51Z
   920  		{-62167219200, 0},              // 0000-01-01T00:00:00Z
   921  		{1661201140, 676836973},        // 2022-08-22T20:45:40.676836973Z
   922  		{253402300799, 999999999},      // 9999-12-31T23:59:59.999999999Z
   923  		{math.MaxInt64, math.MaxInt64}, // -292277022365-05-08T08:17:07Z
   924  	} {
   925  		f.Add(ts[0], ts[1], true, false, 0)
   926  		f.Add(ts[0], ts[1], false, true, 0)
   927  		for _, offset := range []int{0, 60, 60 * 60, 99*60*60 + 99*60, 123456789} {
   928  			f.Add(ts[0], ts[1], false, false, -offset)
   929  			f.Add(ts[0], ts[1], false, false, +offset)
   930  		}
   931  	}
   932  
   933  	f.Fuzz(func(t *testing.T, sec, nsec int64, useUTC, useLocal bool, tzOffset int) {
   934  		var loc *Location
   935  		switch {
   936  		case useUTC:
   937  			loc = UTC
   938  		case useLocal:
   939  			loc = Local
   940  		default:
   941  			loc = FixedZone("", tzOffset)
   942  		}
   943  		ts := Unix(sec, nsec).In(loc)
   944  
   945  		got := AppendFormatRFC3339(ts, nil, false)
   946  		want := AppendFormatAny(ts, nil, RFC3339)
   947  		if !bytes.Equal(got, want) {
   948  			t.Errorf("Format(%s, RFC3339) mismatch:\n\tgot:  %s\n\twant: %s", ts, got, want)
   949  		}
   950  
   951  		gotNanos := AppendFormatRFC3339(ts, nil, true)
   952  		wantNanos := AppendFormatAny(ts, nil, RFC3339Nano)
   953  		if !bytes.Equal(got, want) {
   954  			t.Errorf("Format(%s, RFC3339Nano) mismatch:\n\tgot:  %s\n\twant: %s", ts, gotNanos, wantNanos)
   955  		}
   956  	})
   957  }
   958  
   959  func FuzzParseRFC3339(f *testing.F) {
   960  	for _, tt := range formatTests {
   961  		f.Add(tt.result)
   962  	}
   963  	for _, tt := range parseTests {
   964  		f.Add(tt.value)
   965  	}
   966  	for _, tt := range parseErrorTests {
   967  		f.Add(tt.value)
   968  	}
   969  	for _, tt := range longFractionalDigitsTests {
   970  		f.Add(tt.value)
   971  	}
   972  
   973  	f.Fuzz(func(t *testing.T, s string) {
   974  		// equalTime is like time.Time.Equal, but also compares the time zone.
   975  		equalTime := func(t1, t2 Time) bool {
   976  			name1, offset1 := t1.Zone()
   977  			name2, offset2 := t2.Zone()
   978  			return t1.Equal(t2) && name1 == name2 && offset1 == offset2
   979  		}
   980  
   981  		for _, tz := range []*Location{UTC, Local} {
   982  			// Parsing as RFC3339 or RFC3339Nano should be identical.
   983  			t1, err1 := ParseAny(RFC3339, s, UTC, tz)
   984  			t2, err2 := ParseAny(RFC3339Nano, s, UTC, tz)
   985  			switch {
   986  			case (err1 == nil) != (err2 == nil):
   987  				t.Fatalf("ParseAny(%q) error mismatch:\n\tgot:  %v\n\twant: %v", s, err1, err2)
   988  			case !equalTime(t1, t2):
   989  				t.Fatalf("ParseAny(%q) value mismatch:\n\tgot:  %v\n\twant: %v", s, t1, t2)
   990  			}
   991  
   992  			// TODO(https://go.dev/issue/54580):
   993  			// Remove these checks after ParseAny rejects all invalid RFC 3339.
   994  			if err1 == nil {
   995  				num2 := func(s string) byte { return 10*(s[0]-'0') + (s[1] - '0') }
   996  				switch {
   997  				case len(s) > 12 && s[12] == ':':
   998  					t.Skipf("ParseAny(%q) incorrectly allows single-digit hour fields", s)
   999  				case len(s) > 19 && s[19] == ',':
  1000  					t.Skipf("ParseAny(%q) incorrectly allows comma as sub-second separator", s)
  1001  				case !strings.HasSuffix(s, "Z") && len(s) > 4 && (num2(s[len(s)-5:]) >= 24 || num2(s[len(s)-2:]) >= 60):
  1002  					t.Skipf("ParseAny(%q) incorrectly allows out-of-range zone offset", s)
  1003  				}
  1004  			}
  1005  
  1006  			// Customized parser should be identical to general parser.
  1007  			switch got, ok := ParseRFC3339(s, tz); {
  1008  			case ok != (err1 == nil):
  1009  				t.Fatalf("ParseRFC3339(%q) error mismatch:\n\tgot:  %v\n\twant: %v", s, ok, err1 == nil)
  1010  			case !equalTime(got, t1):
  1011  				t.Fatalf("ParseRFC3339(%q) value mismatch:\n\tgot:  %v\n\twant: %v", s, got, t2)
  1012  			}
  1013  		}
  1014  	})
  1015  }