github.com/go-board/x-go@v0.1.2-0.20220610024734-db1323f6cb15/xtime/parse_test.go (about)

     1  package xtime
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestOne(t *testing.T) {
    12  	time.Local = time.UTC
    13  	var ts time.Time
    14  	ts = MustParse("2018.09.30")
    15  	assert.Equal(t, "2018-09-30 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
    16  }
    17  
    18  type dateTest struct {
    19  	in, out, loc string
    20  	err          bool
    21  }
    22  
    23  var testInputs = []dateTest{
    24  	{in: "oct 7, 1970", out: "1970-10-07 00:00:00 +0000 UTC"},
    25  	{in: "oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"},
    26  	{in: "Oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"},
    27  	{in: "Oct. 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"},
    28  	{in: "oct. 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"},
    29  	{in: "oct. 7, 1970", out: "1970-10-07 00:00:00 +0000 UTC"},
    30  	{in: "Sept. 7, '70", out: "1970-09-07 00:00:00 +0000 UTC"},
    31  	{in: "sept. 7, 1970", out: "1970-09-07 00:00:00 +0000 UTC"},
    32  	{in: "Feb 8, 2009 5:57:51 AM", out: "2009-02-08 05:57:51 +0000 UTC"},
    33  	{in: "May 8, 2009 5:57:51 PM", out: "2009-05-08 17:57:51 +0000 UTC"},
    34  	{in: "May 8, 2009 5:57:1 PM", out: "2009-05-08 17:57:01 +0000 UTC"},
    35  	{in: "May 8, 2009 5:7:51 PM", out: "2009-05-08 17:07:51 +0000 UTC"},
    36  	{in: "May 8, 2009, 5:7:51 PM", out: "2009-05-08 17:07:51 +0000 UTC"},
    37  	{in: "7 oct 70", out: "1970-10-07 00:00:00 +0000 UTC"},
    38  	{in: "7 oct 1970", out: "1970-10-07 00:00:00 +0000 UTC"},
    39  	{in: "7 May 1970", out: "1970-05-07 00:00:00 +0000 UTC"},
    40  	{in: "7 Sep 1970", out: "1970-09-07 00:00:00 +0000 UTC"},
    41  	{in: "7 June 1970", out: "1970-06-07 00:00:00 +0000 UTC"},
    42  	{in: "7 September 1970", out: "1970-09-07 00:00:00 +0000 UTC"},
    43  	//   ANSIC       = "Mon Jan _2 15:04:05 2006"
    44  	{in: "Mon Jan  2 15:04:05 2006", out: "2006-01-02 15:04:05 +0000 UTC"},
    45  	{in: "Thu May 8 17:57:51 2009", out: "2009-05-08 17:57:51 +0000 UTC"},
    46  	{in: "Thu May  8 17:57:51 2009", out: "2009-05-08 17:57:51 +0000 UTC"},
    47  	// RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    48  	{in: "Mon Jan 02 15:04:05 -0700 2006", out: "2006-01-02 22:04:05 +0000 UTC"},
    49  	{in: "Thu May 08 11:57:51 -0700 2009", out: "2009-05-08 18:57:51 +0000 UTC"},
    50  	//   UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    51  	{in: "Mon Jan  2 15:04:05 MST 2006", out: "2006-01-02 15:04:05 +0000 UTC"},
    52  	{in: "Thu May  8 17:57:51 MST 2009", out: "2009-05-08 17:57:51 +0000 UTC"},
    53  	{in: "Thu May  8 17:57:51 PST 2009", out: "2009-05-08 17:57:51 +0000 UTC"},
    54  	{in: "Thu May 08 17:57:51 PST 2009", out: "2009-05-08 17:57:51 +0000 UTC"},
    55  	{in: "Thu May 08 17:57:51 CEST 2009", out: "2009-05-08 17:57:51 +0000 UTC"},
    56  	{in: "Thu May 08 05:05:07 PST 2009", out: "2009-05-08 05:05:07 +0000 UTC"},
    57  	{in: "Thu May 08 5:5:7 PST 2009", out: "2009-05-08 05:05:07 +0000 UTC"},
    58  	// Day Month dd time
    59  	{in: "Mon Aug 10 15:44:11 UTC+0000 2015", out: "2015-08-10 15:44:11 +0000 UTC"},
    60  	{in: "Mon Aug 10 15:44:11 PST-0700 2015", out: "2015-08-10 22:44:11 +0000 UTC"},
    61  	{in: "Mon Aug 10 15:44:11 CEST+0200 2015", out: "2015-08-10 13:44:11 +0000 UTC"},
    62  	{in: "Mon Aug 1 15:44:11 CEST+0200 2015", out: "2015-08-01 13:44:11 +0000 UTC"},
    63  	{in: "Mon Aug 1 5:44:11 CEST+0200 2015", out: "2015-08-01 03:44:11 +0000 UTC"},
    64  	// ??
    65  	{in: "Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)", out: "2015-07-03 17:04:07 +0000 UTC"},
    66  	{in: "Fri Jul 3 2015 06:04:07 GMT+0100 (GMT Daylight Time)", out: "2015-07-03 05:04:07 +0000 UTC"},
    67  	{in: "Fri Jul 3 2015 06:04:07 PST-0700 (Pacific Daylight Time)", out: "2015-07-03 13:04:07 +0000 UTC"},
    68  	// Month dd, yyyy at time
    69  	{in: "September 17, 2012 at 5:00pm UTC-05", out: "2012-09-17 17:00:00 +0000 UTC"},
    70  	{in: "September 17, 2012 at 10:09am PST-08", out: "2012-09-17 18:09:00 +0000 UTC"},
    71  	{in: "September 17, 2012, 10:10:09", out: "2012-09-17 10:10:09 +0000 UTC"},
    72  	{in: "May 17, 2012 at 10:09am PST-08", out: "2012-05-17 18:09:00 +0000 UTC"},
    73  	{in: "May 17, 2012 AT 10:09am PST-08", out: "2012-05-17 18:09:00 +0000 UTC"},
    74  	// Month dd, yyyy time
    75  	{in: "September 17, 2012 5:00pm UTC-05", out: "2012-09-17 17:00:00 +0000 UTC"},
    76  	{in: "September 17, 2012 10:09am PST-08", out: "2012-09-17 18:09:00 +0000 UTC"},
    77  	{in: "September 17, 2012 09:01:00", out: "2012-09-17 09:01:00 +0000 UTC"},
    78  	// Month dd yyyy time
    79  	{in: "September 17 2012 5:00pm UTC-05", out: "2012-09-17 17:00:00 +0000 UTC"},
    80  	{in: "September 17 2012 5:00pm UTC-0500", out: "2012-09-17 17:00:00 +0000 UTC"},
    81  	{in: "September 17 2012 10:09am PST-08", out: "2012-09-17 18:09:00 +0000 UTC"},
    82  	{in: "September 17 2012 5:00PM UTC-05", out: "2012-09-17 17:00:00 +0000 UTC"},
    83  	{in: "September 17 2012 10:09AM PST-08", out: "2012-09-17 18:09:00 +0000 UTC"},
    84  	{in: "September 17 2012 09:01:00", out: "2012-09-17 09:01:00 +0000 UTC"},
    85  	{in: "May 17, 2012 10:10:09", out: "2012-05-17 10:10:09 +0000 UTC"},
    86  	// Month dd, yyyy
    87  	{in: "September 17, 2012", out: "2012-09-17 00:00:00 +0000 UTC"},
    88  	{in: "May 7, 2012", out: "2012-05-07 00:00:00 +0000 UTC"},
    89  	{in: "June 7, 2012", out: "2012-06-07 00:00:00 +0000 UTC"},
    90  	{in: "June 7 2012", out: "2012-06-07 00:00:00 +0000 UTC"},
    91  	// Month dd[th,nd,st,rd] yyyy
    92  	{in: "September 17th, 2012", out: "2012-09-17 00:00:00 +0000 UTC"},
    93  	{in: "September 17th 2012", out: "2012-09-17 00:00:00 +0000 UTC"},
    94  	{in: "September 7th, 2012", out: "2012-09-07 00:00:00 +0000 UTC"},
    95  	{in: "September 7th 2012", out: "2012-09-07 00:00:00 +0000 UTC"},
    96  	{in: "September 7tH 2012", out: "2012-09-07 00:00:00 +0000 UTC"},
    97  	{in: "May 1st 2012", out: "2012-05-01 00:00:00 +0000 UTC"},
    98  	{in: "May 1st, 2012", out: "2012-05-01 00:00:00 +0000 UTC"},
    99  	{in: "May 21st 2012", out: "2012-05-21 00:00:00 +0000 UTC"},
   100  	{in: "May 21st, 2012", out: "2012-05-21 00:00:00 +0000 UTC"},
   101  	{in: "May 23rd 2012", out: "2012-05-23 00:00:00 +0000 UTC"},
   102  	{in: "May 23rd, 2012", out: "2012-05-23 00:00:00 +0000 UTC"},
   103  	{in: "June 2nd, 2012", out: "2012-06-02 00:00:00 +0000 UTC"},
   104  	{in: "June 2nd 2012", out: "2012-06-02 00:00:00 +0000 UTC"},
   105  	{in: "June 22nd, 2012", out: "2012-06-22 00:00:00 +0000 UTC"},
   106  	{in: "June 22nd 2012", out: "2012-06-22 00:00:00 +0000 UTC"},
   107  	// ?
   108  	{in: "Fri, 03 Jul 2015 08:08:08 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   109  	{in: "Fri, 03 Jul 2015 08:08:08 PST", out: "2015-07-03 15:08:08 +0000 UTC", loc: "America/Los_Angeles"},
   110  	{in: "Fri, 03 Jul 2015 08:08:08 PST", out: "2015-07-03 08:08:08 +0000 UTC"},
   111  	{in: "Fri, 3 Jul 2015 08:08:08 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   112  	{in: "Fri, 03 Jul 2015 8:08:08 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   113  	{in: "Fri, 03 Jul 2015 8:8:8 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   114  	// ?
   115  	{in: "Thu, 03 Jul 2017 08:08:04 +0100", out: "2017-07-03 07:08:04 +0000 UTC"},
   116  	{in: "Thu, 03 Jul 2017 08:08:04 -0100", out: "2017-07-03 09:08:04 +0000 UTC"},
   117  	{in: "Thu, 3 Jul 2017 08:08:04 +0100", out: "2017-07-03 07:08:04 +0000 UTC"},
   118  	{in: "Thu, 03 Jul 2017 8:08:04 +0100", out: "2017-07-03 07:08:04 +0000 UTC"},
   119  	{in: "Thu, 03 Jul 2017 8:8:4 +0100", out: "2017-07-03 07:08:04 +0000 UTC"},
   120  	//
   121  	{in: "Tue, 11 Jul 2017 04:08:03 +0200 (CEST)", out: "2017-07-11 02:08:03 +0000 UTC"},
   122  	{in: "Tue, 5 Jul 2017 04:08:03 -0700 (CEST)", out: "2017-07-05 11:08:03 +0000 UTC"},
   123  	{in: "Tue, 11 Jul 2017 04:08:03 +0200 (CEST)", out: "2017-07-11 02:08:03 +0000 UTC", loc: "Europe/Berlin"},
   124  	// day, dd-Mon-yy hh:mm:zz TZ
   125  	{in: "Fri, 03-Jul-15 08:08:08 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   126  	{in: "Fri, 03-Jul-15 08:08:08 PST", out: "2015-07-03 15:08:08 +0000 UTC", loc: "America/Los_Angeles"},
   127  	{in: "Fri, 03-Jul 2015 08:08:08 PST", out: "2015-07-03 08:08:08 +0000 UTC"},
   128  	{in: "Fri, 3-Jul-15 08:08:08 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   129  	{in: "Fri, 03-Jul-15 8:08:08 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   130  	{in: "Fri, 03-Jul-15 8:8:8 MST", out: "2015-07-03 08:08:08 +0000 UTC"},
   131  	// RFC850    = "Monday, 02-Jan-06 15:04:05 MST"
   132  	{in: "Wednesday, 07-May-09 08:00:43 MST", out: "2009-05-07 08:00:43 +0000 UTC"},
   133  	{in: "Wednesday, 28-Feb-18 09:01:00 MST", out: "2018-02-28 09:01:00 +0000 UTC"},
   134  	{in: "Wednesday, 28-Feb-18 09:01:00 MST", out: "2018-02-28 16:01:00 +0000 UTC", loc: "America/Denver"},
   135  	// with offset then with variations on non-zero filled stuff
   136  	{in: "Monday, 02 Jan 2006 15:04:05 +0100", out: "2006-01-02 14:04:05 +0000 UTC"},
   137  	{in: "Wednesday, 28 Feb 2018 09:01:00 -0300", out: "2018-02-28 12:01:00 +0000 UTC"},
   138  	{in: "Wednesday, 2 Feb 2018 09:01:00 -0300", out: "2018-02-02 12:01:00 +0000 UTC"},
   139  	{in: "Wednesday, 2 Feb 2018 9:01:00 -0300", out: "2018-02-02 12:01:00 +0000 UTC"},
   140  	{in: "Wednesday, 2 Feb 2018 09:1:00 -0300", out: "2018-02-02 12:01:00 +0000 UTC"},
   141  	//  dd mon yyyy  12 Feb 2006, 19:17:08
   142  	{in: "07 Feb 2004, 09:07", out: "2004-02-07 09:07:00 +0000 UTC"},
   143  	{in: "07 Feb 2004, 09:07:07", out: "2004-02-07 09:07:07 +0000 UTC"},
   144  	{in: "7 Feb 2004, 09:07:07", out: "2004-02-07 09:07:07 +0000 UTC"},
   145  	{in: "07 Feb 2004, 9:7:7", out: "2004-02-07 09:07:07 +0000 UTC"},
   146  	// dd Mon yyyy hh:mm:ss
   147  	{in: "07 Feb 2004 09:07:08", out: "2004-02-07 09:07:08 +0000 UTC"},
   148  	{in: "07 Feb 2004 09:07", out: "2004-02-07 09:07:00 +0000 UTC"},
   149  	{in: "7 Feb 2004 9:7:8", out: "2004-02-07 09:07:08 +0000 UTC"},
   150  	{in: "07 Feb 2004 09:07:08.123", out: "2004-02-07 09:07:08.123 +0000 UTC"},
   151  	//  dd-mon-yyyy  12 Feb 2006, 19:17:08 GMT
   152  	{in: "07 Feb 2004, 09:07:07 GMT", out: "2004-02-07 09:07:07 +0000 UTC"},
   153  	//  dd-mon-yyyy  12 Feb 2006, 19:17:08 +0100
   154  	{in: "07 Feb 2004, 09:07:07 +0100", out: "2004-02-07 08:07:07 +0000 UTC"},
   155  	//  dd-mon-yyyy   12-Feb-2006 19:17:08
   156  	{in: "07-Feb-2004 09:07:07 +0100", out: "2004-02-07 08:07:07 +0000 UTC"},
   157  	//  dd-mon-yy   12-Feb-2006 19:17:08
   158  	{in: "07-Feb-04 09:07:07 +0100", out: "2004-02-07 08:07:07 +0000 UTC"},
   159  	// yyyy-mon-dd    2013-Feb-03
   160  	{in: "2013-Feb-03", out: "2013-02-03 00:00:00 +0000 UTC"},
   161  	// 03 February 2013
   162  	{in: "03 February 2013", out: "2013-02-03 00:00:00 +0000 UTC"},
   163  	{in: "3 February 2013", out: "2013-02-03 00:00:00 +0000 UTC"},
   164  	// Chinese 2014年04月18日
   165  	{in: "2014年04月08日", out: "2014-04-08 00:00:00 +0000 UTC"},
   166  	{in: "2014年04月08日 19:17:22", out: "2014-04-08 19:17:22 +0000 UTC"},
   167  	//  mm/dd/yyyy
   168  	{in: "03/31/2014", out: "2014-03-31 00:00:00 +0000 UTC"},
   169  	{in: "3/31/2014", out: "2014-03-31 00:00:00 +0000 UTC"},
   170  	{in: "3/5/2014", out: "2014-03-05 00:00:00 +0000 UTC"},
   171  	//  mm/dd/yy
   172  	{in: "08/08/71", out: "1971-08-08 00:00:00 +0000 UTC"},
   173  	{in: "8/8/71", out: "1971-08-08 00:00:00 +0000 UTC"},
   174  	//  mm/dd/yy hh:mm:ss
   175  	{in: "04/02/2014 04:08:09", out: "2014-04-02 04:08:09 +0000 UTC"},
   176  	{in: "4/2/2014 04:08:09", out: "2014-04-02 04:08:09 +0000 UTC"},
   177  	{in: "04/02/2014 4:08:09", out: "2014-04-02 04:08:09 +0000 UTC"},
   178  	{in: "04/02/2014 4:8:9", out: "2014-04-02 04:08:09 +0000 UTC"},
   179  	{in: "04/02/2014 04:08", out: "2014-04-02 04:08:00 +0000 UTC"},
   180  	{in: "04/02/2014 4:8", out: "2014-04-02 04:08:00 +0000 UTC"},
   181  	{in: "04/02/2014 04:08:09.123", out: "2014-04-02 04:08:09.123 +0000 UTC"},
   182  	{in: "04/02/2014 04:08:09.12312", out: "2014-04-02 04:08:09.12312 +0000 UTC"},
   183  	{in: "04/02/2014 04:08:09.123123", out: "2014-04-02 04:08:09.123123 +0000 UTC"},
   184  	//  mm/dd/yy hh:mm:ss AM
   185  	{in: "04/02/2014 04:08:09 AM", out: "2014-04-02 04:08:09 +0000 UTC"},
   186  	{in: "04/02/2014 04:08:09 PM", out: "2014-04-02 16:08:09 +0000 UTC"},
   187  	{in: "04/02/2014 04:08 AM", out: "2014-04-02 04:08:00 +0000 UTC"},
   188  	{in: "04/02/2014 04:08 PM", out: "2014-04-02 16:08:00 +0000 UTC"},
   189  	{in: "04/02/2014 4:8 AM", out: "2014-04-02 04:08:00 +0000 UTC"},
   190  	{in: "04/02/2014 4:8 PM", out: "2014-04-02 16:08:00 +0000 UTC"},
   191  	{in: "04/02/2014 04:08:09.123 AM", out: "2014-04-02 04:08:09.123 +0000 UTC"},
   192  	{in: "04/02/2014 04:08:09.123 PM", out: "2014-04-02 16:08:09.123 +0000 UTC"},
   193  	//   yyyy/mm/dd
   194  	{in: "2014/04/02", out: "2014-04-02 00:00:00 +0000 UTC"},
   195  	{in: "2014/03/31", out: "2014-03-31 00:00:00 +0000 UTC"},
   196  	{in: "2014/4/2", out: "2014-04-02 00:00:00 +0000 UTC"},
   197  	//   yyyy/mm/dd hh:mm:ss AM
   198  	{in: "2014/04/02 04:08", out: "2014-04-02 04:08:00 +0000 UTC"},
   199  	{in: "2014/03/31 04:08", out: "2014-03-31 04:08:00 +0000 UTC"},
   200  	{in: "2014/4/2 04:08", out: "2014-04-02 04:08:00 +0000 UTC"},
   201  	{in: "2014/04/02 4:8", out: "2014-04-02 04:08:00 +0000 UTC"},
   202  	{in: "2014/04/02 04:08:09", out: "2014-04-02 04:08:09 +0000 UTC"},
   203  	{in: "2014/03/31 04:08:09", out: "2014-03-31 04:08:09 +0000 UTC"},
   204  	{in: "2014/4/2 04:08:09", out: "2014-04-02 04:08:09 +0000 UTC"},
   205  	{in: "2014/04/02 04:08:09.123", out: "2014-04-02 04:08:09.123 +0000 UTC"},
   206  	{in: "2014/04/02 04:08:09.123123", out: "2014-04-02 04:08:09.123123 +0000 UTC"},
   207  	{in: "2014/04/02 04:08:09 AM", out: "2014-04-02 04:08:09 +0000 UTC"},
   208  	{in: "2014/03/31 04:08:09 AM", out: "2014-03-31 04:08:09 +0000 UTC"},
   209  	{in: "2014/4/2 04:08:09 AM", out: "2014-04-02 04:08:09 +0000 UTC"},
   210  	{in: "2014/04/02 04:08:09.123 AM", out: "2014-04-02 04:08:09.123 +0000 UTC"},
   211  	{in: "2014/04/02 04:08:09.123 PM", out: "2014-04-02 16:08:09.123 +0000 UTC"},
   212  	//   yyyy-mm-dd
   213  	{in: "2014-04-02", out: "2014-04-02 00:00:00 +0000 UTC"},
   214  	{in: "2014-03-31", out: "2014-03-31 00:00:00 +0000 UTC"},
   215  	{in: "2014-4-2", out: "2014-04-02 00:00:00 +0000 UTC"},
   216  	//   dd-mmm-yy
   217  	{in: "28-Feb-02", out: "2002-02-28 00:00:00 +0000 UTC"},
   218  	{in: "15-Jan-18", out: "2018-01-15 00:00:00 +0000 UTC"},
   219  	{in: "15-Jan-2017", out: "2017-01-15 00:00:00 +0000 UTC"},
   220  	// yyyy-mm
   221  	{in: "2014-04", out: "2014-04-01 00:00:00 +0000 UTC"},
   222  	//   yyyy-mm-dd hh:mm:ss AM
   223  	{in: "2014-04-02 04:08", out: "2014-04-02 04:08:00 +0000 UTC"},
   224  	{in: "2014-03-31 04:08", out: "2014-03-31 04:08:00 +0000 UTC"},
   225  	{in: "2014-4-2 04:08", out: "2014-04-02 04:08:00 +0000 UTC"},
   226  	{in: "2014-04-02 4:8", out: "2014-04-02 04:08:00 +0000 UTC"},
   227  	{in: "2014-04-02 04:08:09", out: "2014-04-02 04:08:09 +0000 UTC"},
   228  	{in: "2014-03-31 04:08:09", out: "2014-03-31 04:08:09 +0000 UTC"},
   229  	{in: "2014-4-2 04:08:09", out: "2014-04-02 04:08:09 +0000 UTC"},
   230  	{in: "2014-04-02 04:08:09.123", out: "2014-04-02 04:08:09.123 +0000 UTC"},
   231  	{in: "2014-04-02 04:08:09.123123", out: "2014-04-02 04:08:09.123123 +0000 UTC"},
   232  	{in: "2014-04-02 04:08:09.12312312", out: "2014-04-02 04:08:09.12312312 +0000 UTC"},
   233  	{in: "2014-04-02 04:08:09 AM", out: "2014-04-02 04:08:09 +0000 UTC"},
   234  	{in: "2014-03-31 04:08:09 AM", out: "2014-03-31 04:08:09 +0000 UTC"},
   235  	{in: "2014-04-26 05:24:37 PM", out: "2014-04-26 17:24:37 +0000 UTC"},
   236  	{in: "2014-4-2 04:08:09 AM", out: "2014-04-02 04:08:09 +0000 UTC"},
   237  	{in: "2014-04-02 04:08:09.123 AM", out: "2014-04-02 04:08:09.123 +0000 UTC"},
   238  	{in: "2014-04-02 04:08:09.123 PM", out: "2014-04-02 16:08:09.123 +0000 UTC"},
   239  	//   yyyy-mm-dd hh:mm:ss,000
   240  	{in: "2014-05-11 08:20:13,787", out: "2014-05-11 08:20:13.787 +0000 UTC"},
   241  	//   yyyy-mm-dd hh:mm:ss +0000
   242  	{in: "2012-08-03 18:31:59 +0000", out: "2012-08-03 18:31:59 +0000 UTC"},
   243  	{in: "2012-08-03 13:31:59 -0600", out: "2012-08-03 19:31:59 +0000 UTC"},
   244  	{in: "2012-08-03 18:31:59.257000000 +0000", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   245  	{in: "2012-08-03 8:1:59.257000000 +0000", out: "2012-08-03 08:01:59.257 +0000 UTC"},
   246  	{in: "2012-8-03 18:31:59.257000000 +0000", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   247  	{in: "2012-8-3 18:31:59.257000000 +0000", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   248  	{in: "2014-04-26 17:24:37.123456 +0000", out: "2014-04-26 17:24:37.123456 +0000 UTC"},
   249  	{in: "2014-04-26 17:24:37.12 +0000", out: "2014-04-26 17:24:37.12 +0000 UTC"},
   250  	{in: "2014-04-26 17:24:37.1 +0000", out: "2014-04-26 17:24:37.1 +0000 UTC"},
   251  	{in: "2014-05-11 08:20:13 +0000", out: "2014-05-11 08:20:13 +0000 UTC"},
   252  	{in: "2014-05-11 08:20:13 +0530", out: "2014-05-11 02:50:13 +0000 UTC"},
   253  	//   yyyy-mm-dd hh:mm:ss +0300 +03  ?? issue author said this is from golang?
   254  	{in: "2018-06-29 19:09:57.77297118 +0300 +03", out: "2018-06-29 16:09:57.77297118 +0000 UTC"},
   255  	{in: "2018-06-29 19:09:57.77297118 +0300 +0300", out: "2018-06-29 16:09:57.77297118 +0000 UTC"},
   256  	{in: "2018-06-29 19:09:57 +0300 +03", out: "2018-06-29 16:09:57 +0000 UTC"},
   257  	{in: "2018-06-29 19:09:57 +0300 +0300", out: "2018-06-29 16:09:57 +0000 UTC"},
   258  
   259  	// 13:31:51.999 -07:00 MST
   260  	//   yyyy-mm-dd hh:mm:ss +00:00
   261  	{in: "2012-08-03 18:31:59 +00:00", out: "2012-08-03 18:31:59 +0000 UTC"},
   262  	{in: "2014-05-01 08:02:13 +00:00", out: "2014-05-01 08:02:13 +0000 UTC"},
   263  	{in: "2014-5-01 08:02:13 +00:00", out: "2014-05-01 08:02:13 +0000 UTC"},
   264  	{in: "2014-05-1 08:02:13 +00:00", out: "2014-05-01 08:02:13 +0000 UTC"},
   265  	{in: "2012-08-03 13:31:59 -06:00", out: "2012-08-03 19:31:59 +0000 UTC"},
   266  	{in: "2012-08-03 18:31:59.257000000 +00:00", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   267  	{in: "2012-08-03 8:1:59.257000000 +00:00", out: "2012-08-03 08:01:59.257 +0000 UTC"},
   268  	{in: "2012-8-03 18:31:59.257000000 +00:00", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   269  	{in: "2012-8-3 18:31:59.257000000 +00:00", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   270  	{in: "2014-04-26 17:24:37.123456 +00:00", out: "2014-04-26 17:24:37.123456 +0000 UTC"},
   271  	{in: "2014-04-26 17:24:37.12 +00:00", out: "2014-04-26 17:24:37.12 +0000 UTC"},
   272  	{in: "2014-04-26 17:24:37.1 +00:00", out: "2014-04-26 17:24:37.1 +0000 UTC"},
   273  	//   yyyy-mm-dd hh:mm:ss +0000 TZ
   274  	// Golang Native Format
   275  	{in: "2012-08-03 18:31:59 +0000 UTC", out: "2012-08-03 18:31:59 +0000 UTC"},
   276  	{in: "2012-08-03 13:31:59 -0600 MST", out: "2012-08-03 19:31:59 +0000 UTC", loc: "America/Denver"},
   277  	{in: "2015-02-18 00:12:00 +0000 UTC", out: "2015-02-18 00:12:00 +0000 UTC"},
   278  	{in: "2015-02-18 00:12:00 +0000 GMT", out: "2015-02-18 00:12:00 +0000 UTC"},
   279  	{in: "2015-02-08 03:02:00 +0200 CEST", out: "2015-02-08 01:02:00 +0000 UTC", loc: "Europe/Berlin"},
   280  	{in: "2015-02-08 03:02:00 +0300 MSK", out: "2015-02-08 00:02:00 +0000 UTC"},
   281  	{in: "2015-2-08 03:02:00 +0300 MSK", out: "2015-02-08 00:02:00 +0000 UTC"},
   282  	{in: "2015-02-8 03:02:00 +0300 MSK", out: "2015-02-08 00:02:00 +0000 UTC"},
   283  	{in: "2015-2-8 03:02:00 +0300 MSK", out: "2015-02-08 00:02:00 +0000 UTC"},
   284  	{in: "2012-08-03 18:31:59.257000000 +0000 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   285  	{in: "2012-08-03 8:1:59.257000000 +0000 UTC", out: "2012-08-03 08:01:59.257 +0000 UTC"},
   286  	{in: "2012-8-03 18:31:59.257000000 +0000 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   287  	{in: "2012-8-3 18:31:59.257000000 +0000 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   288  	{in: "2014-04-26 17:24:37.123456 +0000 UTC", out: "2014-04-26 17:24:37.123456 +0000 UTC"},
   289  	{in: "2014-04-26 17:24:37.12 +0000 UTC", out: "2014-04-26 17:24:37.12 +0000 UTC"},
   290  	{in: "2014-04-26 17:24:37.1 +0000 UTC", out: "2014-04-26 17:24:37.1 +0000 UTC"},
   291  	{in: "2015-02-08 03:02:00 +0200 CEST m=+0.000000001", out: "2015-02-08 01:02:00 +0000 UTC", loc: "Europe/Berlin"},
   292  	{in: "2015-02-08 03:02:00 +0300 MSK m=+0.000000001", out: "2015-02-08 00:02:00 +0000 UTC"},
   293  	{in: "2015-02-08 03:02:00.001 +0300 MSK m=+0.000000001", out: "2015-02-08 00:02:00.001 +0000 UTC"},
   294  	//   yyyy-mm-dd hh:mm:ss TZ
   295  	{in: "2012-08-03 18:31:59 UTC", out: "2012-08-03 18:31:59 +0000 UTC"},
   296  	{in: "2014-12-16 06:20:00 GMT", out: "2014-12-16 06:20:00 +0000 UTC"},
   297  	{in: "2012-08-03 13:31:59 MST", out: "2012-08-03 20:31:59 +0000 UTC", loc: "America/Denver"},
   298  	{in: "2012-08-03 18:31:59.257000000 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   299  	{in: "2012-08-03 8:1:59.257000000 UTC", out: "2012-08-03 08:01:59.257 +0000 UTC"},
   300  	{in: "2012-8-03 18:31:59.257000000 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   301  	{in: "2012-8-3 18:31:59.257000000 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   302  	{in: "2014-04-26 17:24:37.123456 UTC", out: "2014-04-26 17:24:37.123456 +0000 UTC"},
   303  	{in: "2014-04-26 17:24:37.12 UTC", out: "2014-04-26 17:24:37.12 +0000 UTC"},
   304  	{in: "2014-04-26 17:24:37.1 UTC", out: "2014-04-26 17:24:37.1 +0000 UTC"},
   305  	// This one is pretty special, it is TIMEZONE based but starts with P to emulate collions with PM
   306  	{in: "2014-04-26 05:24:37 PST", out: "2014-04-26 05:24:37 +0000 UTC"},
   307  	{in: "2014-04-26 05:24:37 PST", out: "2014-04-26 12:24:37 +0000 UTC", loc: "America/Los_Angeles"},
   308  	//   yyyy-mm-dd hh:mm:ss+00:00
   309  	{in: "2012-08-03 18:31:59+00:00", out: "2012-08-03 18:31:59 +0000 UTC"},
   310  	{in: "2017-07-19 03:21:51+00:00", out: "2017-07-19 03:21:51 +0000 UTC"},
   311  	//   yyyy-mm-dd hh:mm:ss.000+00:00 PST
   312  	{in: "2012-08-03 18:31:59.000+00:00 PST", out: "2012-08-03 18:31:59 +0000 UTC", loc: "America/Los_Angeles"},
   313  	//   yyyy-mm-dd hh:mm:ss +00:00 TZ
   314  	{in: "2012-08-03 18:31:59 +00:00 UTC", out: "2012-08-03 18:31:59 +0000 UTC"},
   315  	{in: "2012-08-03 13:31:51 -07:00 MST", out: "2012-08-03 20:31:51 +0000 UTC", loc: "America/Denver"},
   316  	{in: "2012-08-03 18:31:59.257000000 +00:00 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   317  	{in: "2012-08-03 13:31:51.123 -08:00 PST", out: "2012-08-03 21:31:51.123 +0000 UTC", loc: "America/Los_Angeles"},
   318  	{in: "2012-08-03 13:31:51.123 +02:00 CEST", out: "2012-08-03 11:31:51.123 +0000 UTC", loc: "Europe/Berlin"},
   319  	{in: "2012-08-03 8:1:59.257000000 +00:00 UTC", out: "2012-08-03 08:01:59.257 +0000 UTC"},
   320  	{in: "2012-8-03 18:31:59.257000000 +00:00 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   321  	{in: "2012-8-3 18:31:59.257000000 +00:00 UTC", out: "2012-08-03 18:31:59.257 +0000 UTC"},
   322  	{in: "2014-04-26 17:24:37.123456 +00:00 UTC", out: "2014-04-26 17:24:37.123456 +0000 UTC"},
   323  	{in: "2014-04-26 17:24:37.12 +00:00 UTC", out: "2014-04-26 17:24:37.12 +0000 UTC"},
   324  	{in: "2014-04-26 17:24:37.1 +00:00 UTC", out: "2014-04-26 17:24:37.1 +0000 UTC"},
   325  	//   yyyy-mm-ddThh:mm:ss
   326  	{in: "2009-08-12T22:15:09", out: "2009-08-12 22:15:09 +0000 UTC"},
   327  	{in: "2009-08-08T02:08:08", out: "2009-08-08 02:08:08 +0000 UTC"},
   328  	{in: "2009-08-08T2:8:8", out: "2009-08-08 02:08:08 +0000 UTC"},
   329  	{in: "2009-08-12T22:15:09.123", out: "2009-08-12 22:15:09.123 +0000 UTC"},
   330  	{in: "2009-08-12T22:15:09.123456", out: "2009-08-12 22:15:09.123456 +0000 UTC"},
   331  	{in: "2009-08-12T22:15:09.12", out: "2009-08-12 22:15:09.12 +0000 UTC"},
   332  	{in: "2009-08-12T22:15:09.1", out: "2009-08-12 22:15:09.1 +0000 UTC"},
   333  	{in: "2014-04-26 17:24:37.3186369", out: "2014-04-26 17:24:37.3186369 +0000 UTC"},
   334  	//   yyyy-mm-ddThh:mm:ss-07:00
   335  	{in: "2009-08-12T22:15:09-07:00", out: "2009-08-13 05:15:09 +0000 UTC"},
   336  	{in: "2009-08-12T22:15:09-03:00", out: "2009-08-13 01:15:09 +0000 UTC"},
   337  	{in: "2009-08-12T22:15:9-07:00", out: "2009-08-13 05:15:09 +0000 UTC"},
   338  	{in: "2009-08-12T22:15:09.123-07:00", out: "2009-08-13 05:15:09.123 +0000 UTC"},
   339  	{in: "2016-06-21T19:55:00+01:00", out: "2016-06-21 18:55:00 +0000 UTC"},
   340  	{in: "2016-06-21T19:55:00.799+01:00", out: "2016-06-21 18:55:00.799 +0000 UTC"},
   341  	//   yyyy-mm-ddThh:mm:ss-0700
   342  	{in: "2009-08-12T22:15:09-0700", out: "2009-08-13 05:15:09 +0000 UTC"},
   343  	{in: "2009-08-12T22:15:09-0300", out: "2009-08-13 01:15:09 +0000 UTC"},
   344  	{in: "2009-08-12T22:15:9-0700", out: "2009-08-13 05:15:09 +0000 UTC"},
   345  	{in: "2009-08-12T22:15:09.123-0700", out: "2009-08-13 05:15:09.123 +0000 UTC"},
   346  	{in: "2016-06-21T19:55:00+0100", out: "2016-06-21 18:55:00 +0000 UTC"},
   347  	{in: "2016-06-21T19:55:00.799+0100", out: "2016-06-21 18:55:00.799 +0000 UTC"},
   348  	{in: "2016-06-21T19:55:00+0100", out: "2016-06-21 18:55:00 +0000 UTC"},
   349  	{in: "2016-06-21T19:55:00-0700", out: "2016-06-22 02:55:00 +0000 UTC"},
   350  	{in: "2016-06-21T19:55:00.799+0100", out: "2016-06-21 18:55:00.799 +0000 UTC"},
   351  	{in: "2016-06-21T19:55+0100", out: "2016-06-21 18:55:00 +0000 UTC"},
   352  	{in: "2016-06-21T19:55+0130", out: "2016-06-21 18:25:00 +0000 UTC"},
   353  	//   yyyy-mm-ddThh:mm:ssZ
   354  	{in: "2009-08-12T22:15Z", out: "2009-08-12 22:15:00 +0000 UTC"},
   355  	{in: "2009-08-12T22:15:09Z", out: "2009-08-12 22:15:09 +0000 UTC"},
   356  	{in: "2009-08-12T22:15:09.99Z", out: "2009-08-12 22:15:09.99 +0000 UTC"},
   357  	{in: "2009-08-12T22:15:09.9999Z", out: "2009-08-12 22:15:09.9999 +0000 UTC"},
   358  	{in: "2009-08-12T22:15:09.99999999Z", out: "2009-08-12 22:15:09.99999999 +0000 UTC"},
   359  	{in: "2009-08-12T22:15:9.99999999Z", out: "2009-08-12 22:15:09.99999999 +0000 UTC"},
   360  	// yyyy.mm
   361  	{in: "2014.05", out: "2014-05-01 00:00:00 +0000 UTC"},
   362  	{in: "2018.09.30", out: "2018-09-30 00:00:00 +0000 UTC"},
   363  
   364  	//   mm.dd.yyyy
   365  	{in: "3.31.2014", out: "2014-03-31 00:00:00 +0000 UTC"},
   366  	{in: "3.3.2014", out: "2014-03-03 00:00:00 +0000 UTC"},
   367  	{in: "03.31.2014", out: "2014-03-31 00:00:00 +0000 UTC"},
   368  	//   mm.dd.yy
   369  	{in: "08.21.71", out: "1971-08-21 00:00:00 +0000 UTC"},
   370  	//  yyyymmdd and similar
   371  	{in: "2014", out: "2014-01-01 00:00:00 +0000 UTC"},
   372  	{in: "20140601", out: "2014-06-01 00:00:00 +0000 UTC"},
   373  	{in: "20140722105203", out: "2014-07-22 10:52:03 +0000 UTC"},
   374  
   375  	// all digits:  unix secs, ms etc
   376  	{in: "1332151919", out: "2012-03-19 10:11:59 +0000 UTC"},
   377  	{in: "1332151919", out: "2012-03-19 10:11:59 +0000 UTC", loc: "America/Denver"},
   378  	{in: "1384216367111", out: "2013-11-12 00:32:47.111 +0000 UTC"},
   379  	{in: "1384216367111222", out: "2013-11-12 00:32:47.111222 +0000 UTC"},
   380  	{in: "1384216367111222333", out: "2013-11-12 00:32:47.111222333 +0000 UTC"},
   381  }
   382  
   383  func TestParse(t *testing.T) {
   384  
   385  	// Lets ensure we are operating on UTC
   386  	time.Local = time.UTC
   387  
   388  	zeroTime := time.Time{}.Unix()
   389  	ts, err := ParseAny("INVALID")
   390  	assert.Equal(t, zeroTime, ts.Unix())
   391  	assert.NotEqual(t, nil, err)
   392  
   393  	assert.Equal(t, true, testDidPanic("NOT GONNA HAPPEN"))
   394  	// https://github.com/golang/go/issues/5294
   395  	_, err = ParseAny(time.RFC3339)
   396  	assert.NotEqual(t, nil, err)
   397  
   398  	for _, th := range testInputs {
   399  		if len(th.loc) > 0 {
   400  			loc, err := time.LoadLocation(th.loc)
   401  			if err != nil {
   402  				t.Fatalf("Expected to load location %q but got %v", th.loc, err)
   403  			}
   404  			ts, err = ParseIn(th.in, loc)
   405  			if err != nil {
   406  				t.Fatalf("expected to parse %q but got %v", th.in, err)
   407  			}
   408  			got := fmt.Sprintf("%v", ts.In(time.UTC))
   409  			assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in)
   410  			if th.out != got {
   411  				panic("whoops")
   412  			}
   413  		} else {
   414  			ts = MustParse(th.in)
   415  			got := fmt.Sprintf("%v", ts.In(time.UTC))
   416  			assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in)
   417  			if th.out != got {
   418  				panic("whoops")
   419  			}
   420  		}
   421  	}
   422  
   423  	// some errors
   424  
   425  	assert.Equal(t, true, testDidPanic(`{"ts":"now"}`))
   426  
   427  	_, err = ParseAny("138421636711122233311111") // too many digits
   428  	assert.NotEqual(t, nil, err)
   429  
   430  	_, err = ParseAny("-1314")
   431  	assert.NotEqual(t, nil, err)
   432  
   433  	_, err = ParseAny("2014-13-13 08:20:13,787") // month 13 doesn't exist so error
   434  	assert.NotEqual(t, nil, err)
   435  }
   436  
   437  func testDidPanic(datestr string) (paniced bool) {
   438  	defer func() {
   439  		if r := recover(); r != nil {
   440  			paniced = true
   441  		}
   442  	}()
   443  	MustParse(datestr)
   444  	return false
   445  }
   446  
   447  func TestPStruct(t *testing.T) {
   448  
   449  	denverLoc, err := time.LoadLocation("America/Denver")
   450  	assert.Equal(t, nil, err)
   451  
   452  	p := newParser("08.21.71", denverLoc)
   453  
   454  	p.setMonth()
   455  	assert.Equal(t, 0, p.moi)
   456  	p.setDay()
   457  	assert.Equal(t, 0, p.dayi)
   458  	p.set(-1, "not")
   459  	p.set(15, "not")
   460  	assert.Equal(t, "08.21.71", p.datestr)
   461  	assert.Equal(t, "08.21.71", string(p.format))
   462  	assert.True(t, len(p.ds()) > 0)
   463  	assert.True(t, len(p.ts()) > 0)
   464  }
   465  
   466  var testParseErrors = []dateTest{
   467  	{in: "3", err: true},
   468  	{in: `{"hello"}`, err: true},
   469  	{in: "2009-15-12T22:15Z", err: true},
   470  	{in: "5,000-9,999", err: true},
   471  	{in: "xyzq-baad"},
   472  	{in: "oct.-7-1970", err: true},
   473  	{in: "septe. 7, 1970", err: true},
   474  	{in: "SeptemberRR 7th, 1970", err: true},
   475  	{in: "29-06-2016", err: true},
   476  	// this is just testing the empty space up front
   477  	{in: " 2018-01-02 17:08:09 -07:00", err: true},
   478  }
   479  
   480  func TestParseErrors(t *testing.T) {
   481  	for _, th := range testParseErrors {
   482  		v, err := ParseAny(th.in)
   483  		assert.NotEqual(t, nil, err, "%v for %v", v, th.in)
   484  	}
   485  }
   486  
   487  var testParseFormat = []dateTest{
   488  	// errors
   489  	{in: "3", err: true},
   490  	{in: `{"hello"}`, err: true},
   491  	{in: "2009-15-12T22:15Z", err: true},
   492  	{in: "5,000-9,999", err: true},
   493  	//
   494  	{in: "oct 7, 1970", out: "Jan 2, 2006"},
   495  	{in: "sept. 7, 1970", out: "Jan. 2, 2006"},
   496  	{in: "May 05, 2015, 05:05:07", out: "Jan 02, 2006, 15:04:05"},
   497  	// 03 February 2013
   498  	{in: "03 February 2013", out: "02 January 2006"},
   499  	// 13:31:51.999 -07:00 MST
   500  	//   yyyy-mm-dd hh:mm:ss +00:00
   501  	{in: "2012-08-03 18:31:59 +00:00", out: "2006-01-02 15:04:05 -07:00"},
   502  	//   yyyy-mm-dd hh:mm:ss +0000 TZ
   503  	// Golang Native Format
   504  	{in: "2012-08-03 18:31:59 +0000 UTC", out: "2006-01-02 15:04:05 -0700 UTC"},
   505  	//   yyyy-mm-dd hh:mm:ss TZ
   506  	{in: "2012-08-03 18:31:59 UTC", out: "2006-01-02 15:04:05 UTC"},
   507  	//   yyyy-mm-ddThh:mm:ss-07:00
   508  	{in: "2009-08-12T22:15:09-07:00", out: "2006-01-02T15:04:05-07:00"},
   509  	//   yyyy-mm-ddThh:mm:ss-0700
   510  	{in: "2009-08-12T22:15:09-0700", out: "2006-01-02T15:04:05-0700"},
   511  	//   yyyy-mm-ddThh:mm:ssZ
   512  	{in: "2009-08-12T22:15Z", out: "2006-01-02T15:04Z"},
   513  }
   514  
   515  func TestParseLayout(t *testing.T) {
   516  	for _, th := range testParseFormat {
   517  		l, err := ParseFormat(th.in)
   518  		if th.err {
   519  			assert.NotEqual(t, nil, err)
   520  		} else {
   521  			assert.Equal(t, nil, err)
   522  			assert.Equal(t, th.out, l, "for in=%v", th.in)
   523  		}
   524  	}
   525  }
   526  
   527  var testParseStrict = []dateTest{
   528  	//   dd-mon-yy  13-Feb-03
   529  	{in: "03-03-14"},
   530  	//   mm.dd.yyyy
   531  	{in: "3.3.2014"},
   532  	//   mm.dd.yy
   533  	{in: "08.09.71"},
   534  	//  mm/dd/yyyy
   535  	{in: "3/5/2014"},
   536  	//  mm/dd/yy
   537  	{in: "08/08/71"},
   538  	{in: "8/8/71"},
   539  	//  mm/dd/yy hh:mm:ss
   540  	{in: "04/02/2014 04:08:09"},
   541  	{in: "4/2/2014 04:08:09"},
   542  }
   543  
   544  func TestParseStrict(t *testing.T) {
   545  
   546  	for _, th := range testParseStrict {
   547  		_, err := ParseStrict(th.in)
   548  		assert.NotEqual(t, nil, err)
   549  	}
   550  
   551  	_, err := ParseStrict(`{"hello"}`)
   552  	assert.NotEqual(t, nil, err)
   553  
   554  	_, err = ParseStrict("2009-08-12T22:15Z")
   555  	assert.Equal(t, nil, err)
   556  }
   557  
   558  // Lets test to see how this performs using different Timezones/Locations
   559  // Also of note, try changing your server/machine timezones and repeat
   560  //
   561  // !!!!! The time-zone of local machine effects the results!
   562  // https://play.golang.org/p/IDHRalIyXh
   563  // https://github.com/golang/go/issues/18012
   564  func TestInLocation(t *testing.T) {
   565  
   566  	denverLoc, err := time.LoadLocation("America/Denver")
   567  	assert.Equal(t, nil, err)
   568  
   569  	// Start out with time.UTC
   570  	time.Local = time.UTC
   571  
   572  	// Just normal parse to test out zone/offset
   573  	ts := MustParse("2013-02-01 00:00:00")
   574  	zone, offset := ts.Zone()
   575  	assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
   576  	assert.Equal(t, "UTC", zone, "Should have found zone = UTC %v", zone)
   577  	assert.Equal(t, "2013-02-01 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   578  
   579  	// Now lets set to denver (MST/MDT) and re-parse the same time string
   580  	// and since no timezone info in string, we expect same result
   581  	time.Local = denverLoc
   582  	ts = MustParse("2013-02-01 00:00:00")
   583  	zone, offset = ts.Zone()
   584  	assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
   585  	assert.Equal(t, "UTC", zone, "Should have found zone = UTC %v", zone)
   586  	assert.Equal(t, "2013-02-01 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   587  
   588  	ts = MustParse("Tue, 5 Jul 2017 16:28:13 -0700 (MST)")
   589  	assert.Equal(t, "2017-07-05 23:28:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   590  
   591  	// Now we are going to use ParseIn() and see that it gives different answer
   592  	// with different zone, offset
   593  	time.Local = nil
   594  	ts, err = ParseIn("2013-02-01 00:00:00", denverLoc)
   595  	assert.Equal(t, nil, err)
   596  	zone, offset = ts.Zone()
   597  	assert.Equal(t, -25200, offset, "Should have found offset = -25200 %v  %v", offset, denverLoc)
   598  	assert.Equal(t, "MST", zone, "Should have found zone = MST %v", zone)
   599  	assert.Equal(t, "2013-02-01 07:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   600  
   601  	ts, err = ParseIn("18 January 2018", denverLoc)
   602  	assert.Equal(t, nil, err)
   603  	zone, offset = ts.Zone()
   604  	assert.Equal(t, -25200, offset, "Should have found offset = 0 %v", offset)
   605  	assert.Equal(t, "MST", zone, "Should have found zone = UTC %v", zone)
   606  	assert.Equal(t, "2018-01-18 07:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   607  
   608  	// Now we are going to use ParseLocal() and see that it gives same
   609  	// answer as ParseIn when we have time.Local set to a location
   610  	time.Local = denverLoc
   611  	ts, err = ParseLocal("2013-02-01 00:00:00")
   612  	assert.Equal(t, nil, err)
   613  	zone, offset = ts.Zone()
   614  	assert.Equal(t, -25200, offset, "Should have found offset = -25200 %v  %v", offset, denverLoc)
   615  	assert.Equal(t, "MST", zone, "Should have found zone = MST %v", zone)
   616  	assert.Equal(t, "2013-02-01 07:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   617  
   618  	// Lets advance past daylight savings time start
   619  	// use parseIn and see offset/zone has changed to Daylight Savings Equivalents
   620  	ts, err = ParseIn("2013-04-01 00:00:00", denverLoc)
   621  	assert.Equal(t, nil, err)
   622  	zone, offset = ts.Zone()
   623  	assert.Equal(t, -21600, offset, "Should have found offset = -21600 %v  %v", offset, denverLoc)
   624  	assert.Equal(t, "MDT", zone, "Should have found zone = MDT %v", zone)
   625  	assert.Equal(t, "2013-04-01 06:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   626  
   627  	// reset to UTC
   628  	time.Local = time.UTC
   629  
   630  	//   UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
   631  	ts = MustParse("Mon Jan  2 15:04:05 MST 2006")
   632  
   633  	_, offset = ts.Zone()
   634  	assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
   635  	assert.Equal(t, "2006-01-02 15:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   636  
   637  	// Now lets set to denver(mst/mdt)
   638  	time.Local = denverLoc
   639  	ts = MustParse("Mon Jan  2 15:04:05 MST 2006")
   640  
   641  	// this time is different from one above parsed with time.Local set to UTC
   642  	_, offset = ts.Zone()
   643  	assert.Equal(t, -25200, offset, "Should have found offset = -25200 %v", offset)
   644  	assert.Equal(t, "2006-01-02 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   645  
   646  	// Now Reset To UTC
   647  	time.Local = time.UTC
   648  
   649  	// RFC850    = "Monday, 02-Jan-06 15:04:05 MST"
   650  	ts = MustParse("Monday, 02-Jan-06 15:04:05 MST")
   651  	_, offset = ts.Zone()
   652  	assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
   653  	assert.Equal(t, "2006-01-02 15:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   654  
   655  	// Now lets set to denver
   656  	time.Local = denverLoc
   657  	ts = MustParse("Monday, 02-Jan-06 15:04:05 MST")
   658  	_, offset = ts.Zone()
   659  	assert.NotEqual(t, 0, offset, "Should have found offset %v", offset)
   660  	assert.Equal(t, "2006-01-02 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
   661  
   662  	// Now some errors
   663  	zeroTime := time.Time{}.Unix()
   664  	ts, err = ParseIn("INVALID", denverLoc)
   665  	assert.Equal(t, zeroTime, ts.Unix())
   666  	assert.NotEqual(t, nil, err)
   667  
   668  	ts, err = ParseLocal("INVALID")
   669  	assert.Equal(t, zeroTime, ts.Unix())
   670  	assert.NotEqual(t, nil, err)
   671  }