Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
6c124cb8
Commit
6c124cb8
authored
Apr 27, 2010
by
Micah Stetson
Committed by
Russ Cox
Apr 27, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
time: remove incorrect time.ISO8601 and add time.RFC3339
Fixes #734. R=rsc, r CC=golang-dev
https://golang.org/cl/975042
parent
a83c5f5c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
88 additions
and
54 deletions
+88
-54
format.go
src/pkg/time/format.go
+77
-43
time_test.go
src/pkg/time/time_test.go
+11
-11
No files found.
src/pkg/time/format.go
View file @
6c124cb8
...
...
@@ -24,6 +24,15 @@ const (
// may be replaced by a digit if the following number
// (a day) has two digits; for compatibility with
// fixed-width Unix time formats.
//
// Numeric time zone offsets format as follows:
// -0700 ±hhmm
// -07:00 ±hh:mm
// Replacing the sign in the format with a Z triggers
// the ISO 8601 behavior of printing Z instead of an
// offset for the UTC zone. Thus:
// Z0700 Z or ±hhmm
// Z07:00 Z or ±hh:mm
const
(
ANSIC
=
"Mon Jan _2 15:04:05 2006"
UnixDate
=
"Mon Jan _2 15:04:05 MST 2006"
...
...
@@ -34,35 +43,35 @@ const (
RFC850
=
"Monday, 02-Jan-06 15:04:05 MST"
RFC1123
=
"Mon, 02 Jan 2006 15:04:05 MST"
Kitchen
=
"3:04PM"
// Special case: use Z to get the time zone formatted according to ISO 8601,
// which is -0700 or Z for UTC
ISO8601
=
"2006-01-02T15:04:05Z"
RFC3339
=
"2006-01-02T15:04:05Z07:00"
)
const
(
stdLongMonth
=
"January"
stdMonth
=
"Jan"
stdNumMonth
=
"1"
stdZeroMonth
=
"01"
stdLongWeekDay
=
"Monday"
stdWeekDay
=
"Mon"
stdDay
=
"2"
stdUnderDay
=
"_2"
stdZeroDay
=
"02"
stdHour
=
"15"
stdHour12
=
"3"
stdZeroHour12
=
"03"
stdMinute
=
"4"
stdZeroMinute
=
"04"
stdSecond
=
"5"
stdZeroSecond
=
"05"
stdLongYear
=
"2006"
stdYear
=
"06"
stdPM
=
"PM"
stdpm
=
"pm"
stdTZ
=
"MST"
stdISO8601TZ
=
"Z"
// prints Z for UTC
stdNumTZ
=
"-0700"
// always numeric
stdLongMonth
=
"January"
stdMonth
=
"Jan"
stdNumMonth
=
"1"
stdZeroMonth
=
"01"
stdLongWeekDay
=
"Monday"
stdWeekDay
=
"Mon"
stdDay
=
"2"
stdUnderDay
=
"_2"
stdZeroDay
=
"02"
stdHour
=
"15"
stdHour12
=
"3"
stdZeroHour12
=
"03"
stdMinute
=
"4"
stdZeroMinute
=
"04"
stdSecond
=
"5"
stdZeroSecond
=
"05"
stdLongYear
=
"2006"
stdYear
=
"06"
stdPM
=
"PM"
stdpm
=
"pm"
stdTZ
=
"MST"
stdISO8601TZ
=
"Z0700"
// prints Z for UTC
stdISO8601ColonTZ
=
"Z07:00"
// prints Z for UTC
stdNumTZ
=
"-0700"
// always numeric
stdNumColonTZ
=
"-07:00"
// always numeric
)
// nextStdChunk finds the first occurrence of a std string in
...
...
@@ -113,7 +122,7 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
return
layout
[
0
:
i
],
stdUnderDay
,
layout
[
i
+
2
:
]
}
case
'3'
,
'4'
,
'5'
,
'Z'
:
// 3, 4, 5, Z
case
'3'
,
'4'
,
'5'
:
// 3, 4, 5
return
layout
[
0
:
i
],
layout
[
i
:
i
+
1
],
layout
[
i
+
1
:
]
case
'P'
:
// PM
...
...
@@ -126,10 +135,20 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
return
layout
[
0
:
i
],
layout
[
i
:
i
+
2
],
layout
[
i
+
2
:
]
}
case
'-'
:
// -0700
case
'-'
:
// -0700
, -07:00
if
len
(
layout
)
>=
i
+
5
&&
layout
[
i
:
i
+
5
]
==
stdNumTZ
{
return
layout
[
0
:
i
],
layout
[
i
:
i
+
5
],
layout
[
i
+
5
:
]
}
if
len
(
layout
)
>=
i
+
6
&&
layout
[
i
:
i
+
6
]
==
stdNumColonTZ
{
return
layout
[
0
:
i
],
layout
[
i
:
i
+
6
],
layout
[
i
+
6
:
]
}
case
'Z'
:
// Z0700, Z07:00
if
len
(
layout
)
>=
i
+
5
&&
layout
[
i
:
i
+
5
]
==
stdISO8601TZ
{
return
layout
[
0
:
i
],
layout
[
i
:
i
+
5
],
layout
[
i
+
5
:
]
}
if
len
(
layout
)
>=
i
+
6
&&
layout
[
i
:
i
+
6
]
==
stdISO8601ColonTZ
{
return
layout
[
0
:
i
],
layout
[
i
:
i
+
6
],
layout
[
i
+
6
:
]
}
}
}
return
layout
,
""
,
""
...
...
@@ -210,7 +229,7 @@ func zeroPad(i int) string { return pad(i, "0") }
// according to layout. The layout defines the format by showing the
// representation of a standard time, which is then used to describe
// the time to be formatted. Predefined layouts ANSIC, UnixDate,
//
ISO8601
and others describe standard representations.
//
RFC3339
and others describe standard representations.
func
(
t
*
Time
)
Format
(
layout
string
)
string
{
b
:=
new
(
bytes
.
Buffer
)
// Each iteration generates one std value.
...
...
@@ -258,10 +277,10 @@ func (t *Time) Format(layout string) string {
p
=
strconv
.
Itoa
(
t
.
Second
)
case
stdZeroSecond
:
p
=
zeroPad
(
t
.
Second
)
case
stdISO8601TZ
,
std
Num
TZ
:
// Ugly special case. We cheat and take
"Z" to mean "the time
// zone as formatted for ISO 8601".
if
std
==
stdISO8601TZ
&&
t
.
ZoneOffset
==
0
{
case
stdISO8601TZ
,
std
ISO8601ColonTZ
,
stdNumTZ
,
stdNumColon
TZ
:
// Ugly special case. We cheat and take
the "Z" variants
//
to mean "the time
zone as formatted for ISO 8601".
if
t
.
ZoneOffset
==
0
&&
std
[
0
]
==
'Z'
{
p
=
"Z"
break
}
...
...
@@ -273,6 +292,9 @@ func (t *Time) Format(layout string) string {
p
=
"+"
}
p
+=
zeroPad
(
zone
/
60
)
if
std
==
stdISO8601ColonTZ
||
std
==
stdNumColonTZ
{
p
+=
":"
}
p
+=
zeroPad
(
zone
%
60
)
case
stdPM
:
if
t
.
Hour
>=
12
{
...
...
@@ -383,7 +405,7 @@ func skip(value, prefix string) (string, os.Error) {
// Parse parses a formatted string and returns the time value it represents.
// The layout defines the format by showing the representation of a standard
// time, which is then used to describe the string to be parsed. Predefined
// layouts ANSIC, UnixDate,
ISO8601
and others describe standard
// layouts ANSIC, UnixDate,
RFC3339
and others describe standard
// representations.
//
// Only those elements present in the value will be set in the returned time
...
...
@@ -475,22 +497,34 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
if
t
.
Second
<
0
||
60
<=
t
.
Second
{
rangeErrString
=
"second"
}
case
stdISO8601TZ
,
std
Num
TZ
:
if
std
==
stdISO8601TZ
&&
len
(
value
)
>=
1
&&
value
[
0
]
==
'Z'
{
case
stdISO8601TZ
,
std
ISO8601ColonTZ
,
stdNumTZ
,
stdNumColon
TZ
:
if
std
[
0
]
==
'Z'
&&
len
(
value
)
>=
1
&&
value
[
0
]
==
'Z'
{
value
=
value
[
1
:
]
t
.
Zone
=
"UTC"
break
}
if
len
(
value
)
<
5
{
err
=
errBad
break
var
sign
,
hh
,
mm
string
if
std
==
stdISO8601ColonTZ
||
std
==
stdNumColonTZ
{
if
len
(
value
)
<
6
{
err
=
errBad
break
}
if
value
[
3
]
!=
':'
{
err
=
errBad
break
}
sign
,
hh
,
mm
,
value
=
value
[
0
:
1
],
value
[
1
:
3
],
value
[
4
:
6
],
value
[
6
:
]
}
else
{
if
len
(
value
)
<
5
{
err
=
errBad
break
}
sign
,
hh
,
mm
,
value
=
value
[
0
:
1
],
value
[
1
:
3
],
value
[
3
:
5
],
value
[
5
:
]
}
var
sign
string
sign
,
p
,
value
=
value
[
0
:
1
],
value
[
1
:
5
],
value
[
5
:
]
var
hr
,
min
int
hr
,
err
=
strconv
.
Atoi
(
p
[
0
:
2
]
)
hr
,
err
=
strconv
.
Atoi
(
hh
)
if
err
!=
nil
{
min
,
err
=
strconv
.
Atoi
(
p
[
2
:
4
]
)
min
,
err
=
strconv
.
Atoi
(
mm
)
}
t
.
ZoneOffset
=
(
hr
*
60
+
min
)
*
60
// offset is in seconds
switch
sign
[
0
]
{
...
...
src/pkg/time/time_test.go
View file @
6c124cb8
...
...
@@ -107,18 +107,18 @@ type TimeFormatTest struct {
formattedValue
string
}
var
iso8601
Formats
=
[]
TimeFormatTest
{
var
rfc3339
Formats
=
[]
TimeFormatTest
{
TimeFormatTest
{
Time
{
2008
,
9
,
17
,
20
,
4
,
26
,
Wednesday
,
0
,
"UTC"
},
"2008-09-17T20:04:26Z"
},
TimeFormatTest
{
Time
{
1994
,
9
,
17
,
20
,
4
,
26
,
Wednesday
,
-
18000
,
"EST"
},
"1994-09-17T20:04:26-0500"
},
TimeFormatTest
{
Time
{
2000
,
12
,
26
,
1
,
15
,
6
,
Wednesday
,
15600
,
"OTO"
},
"2000-12-26T01:15:06+0420"
},
TimeFormatTest
{
Time
{
1994
,
9
,
17
,
20
,
4
,
26
,
Wednesday
,
-
18000
,
"EST"
},
"1994-09-17T20:04:26-05
:
00"
},
TimeFormatTest
{
Time
{
2000
,
12
,
26
,
1
,
15
,
6
,
Wednesday
,
15600
,
"OTO"
},
"2000-12-26T01:15:06+04
:
20"
},
}
func
Test
ISO8601
Conversion
(
t
*
testing
.
T
)
{
for
_
,
f
:=
range
iso8601
Formats
{
if
f
.
time
.
Format
(
ISO8601
)
!=
f
.
formattedValue
{
t
.
Error
(
"
ISO8601
:"
)
func
Test
RFC3339
Conversion
(
t
*
testing
.
T
)
{
for
_
,
f
:=
range
rfc3339
Formats
{
if
f
.
time
.
Format
(
RFC3339
)
!=
f
.
formattedValue
{
t
.
Error
(
"
RFC3339
:"
)
t
.
Errorf
(
" want=%+v"
,
f
.
formattedValue
)
t
.
Errorf
(
" have=%+v"
,
f
.
time
.
Format
(
ISO8601
))
t
.
Errorf
(
" have=%+v"
,
f
.
time
.
Format
(
RFC3339
))
}
}
}
...
...
@@ -136,7 +136,7 @@ var formatTests = []FormatTest{
FormatTest
{
"RFC822"
,
RFC822
,
"04 Feb 10 2100 PST"
},
FormatTest
{
"RFC850"
,
RFC850
,
"Thursday, 04-Feb-10 21:00:57 PST"
},
FormatTest
{
"RFC1123"
,
RFC1123
,
"Thu, 04 Feb 2010 21:00:57 PST"
},
FormatTest
{
"
ISO8601"
,
ISO8601
,
"2010-02-04T21:00:57-08
00"
},
FormatTest
{
"
RFC3339"
,
RFC3339
,
"2010-02-04T21:00:57-08:
00"
},
FormatTest
{
"Kitchen"
,
Kitchen
,
"9:00PM"
},
FormatTest
{
"am/pm"
,
"3pm"
,
"9pm"
},
FormatTest
{
"AM/PM"
,
"3PM"
,
"9PM"
},
...
...
@@ -168,7 +168,7 @@ var parseTests = []ParseTest{
ParseTest
{
"RubyDate"
,
RubyDate
,
"Thu Feb 04 21:00:57 -0800 2010"
,
true
,
true
,
1
},
ParseTest
{
"RFC850"
,
RFC850
,
"Thursday, 04-Feb-10 21:00:57 PST"
,
true
,
true
,
1
},
ParseTest
{
"RFC1123"
,
RFC1123
,
"Thu, 04 Feb 2010 21:00:57 PST"
,
true
,
true
,
1
},
ParseTest
{
"
ISO8601"
,
ISO8601
,
"2010-02-04T21:00:57-08
00"
,
true
,
false
,
1
},
ParseTest
{
"
RFC3339"
,
RFC3339
,
"2010-02-04T21:00:57-08:
00"
,
true
,
false
,
1
},
// Amount of white space should not matter.
ParseTest
{
"ANSIC"
,
ANSIC
,
"Thu Feb 4 21:00:57 2010"
,
false
,
true
,
1
},
ParseTest
{
"ANSIC"
,
ANSIC
,
"Thu Feb 4 21:00:57 2010"
,
false
,
true
,
1
},
...
...
@@ -234,7 +234,7 @@ func checkTime(time *Time, test *ParseTest, t *testing.T) {
}
func
TestFormatAndParse
(
t
*
testing
.
T
)
{
const
fmt
=
"Mon MST "
+
ISO8601
// all fields
const
fmt
=
"Mon MST "
+
RFC3339
// all fields
f
:=
func
(
sec
int64
)
bool
{
t1
:=
SecondsToLocalTime
(
sec
)
if
t1
.
Year
<
1000
||
t1
.
Year
>
9999
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment