summaryrefslogtreecommitdiff
path: root/src/pkg/time/format.go
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-08-10 15:05:15 +0200
committerOndřej Surý <ondrej@sury.org>2011-08-10 15:05:15 +0200
commit825e92f34920934f09dbf4c614dbd2913ba464cb (patch)
tree2af4eb446f544e17f65b34ad2b9668d2bb8ab78b /src/pkg/time/format.go
parente6b380032482808aee5e4c5222b6d7390f468e74 (diff)
downloadgolang-825e92f34920934f09dbf4c614dbd2913ba464cb.tar.gz
Imported Upstream version 2011.08.10upstream-weekly/2011.08.10
Diffstat (limited to 'src/pkg/time/format.go')
-rw-r--r--src/pkg/time/format.go66
1 files changed, 65 insertions, 1 deletions
diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go
index d07e1ad49..3c42f0c2d 100644
--- a/src/pkg/time/format.go
+++ b/src/pkg/time/format.go
@@ -26,6 +26,9 @@ const (
// replaced by a digit if the following number (a day) has two digits; for
// compatibility with fixed-width Unix time formats.
//
+// A decimal point followed by one or more zeros represents a
+// fractional second.
+//
// Numeric time zone offsets format as follows:
// -0700 ±hhmm
// -07:00 ±hh:mm
@@ -45,6 +48,11 @@ const (
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC3339 = "2006-01-02T15:04:05Z07:00"
Kitchen = "3:04PM"
+ // Handy time stamps.
+ Stamp = "Jan _2 15:04:05"
+ StampMilli = "Jan _2 15:04:05.000"
+ StampMicro = "Jan _2 15:04:05.000000"
+ StampNano = "Jan _2 15:04:05.000000000"
)
const (
@@ -154,6 +162,16 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
if len(layout) >= i+6 && layout[i:i+6] == stdISO8601ColonTZ {
return layout[0:i], layout[i : i+6], layout[i+6:]
}
+ case '.': // .000 - multiple digits of zeros (only) for fractional seconds.
+ numZeros := 0
+ var j int
+ for j = i + 1; j < len(layout) && layout[j] == '0'; j++ {
+ numZeros++
+ }
+ // String of digits must end here - only fractional second is all zeros.
+ if numZeros > 0 && (j >= len(layout) || layout[j] < '0' || '9' < layout[j]) {
+ return layout[0:i], layout[i : i+1+numZeros], layout[i+1+numZeros:]
+ }
}
}
return layout, "", ""
@@ -230,6 +248,21 @@ func pad(i int, padding string) string {
func zeroPad(i int) string { return pad(i, "0") }
+// formatNano formats a fractional second, as nanoseconds.
+func formatNano(nanosec, n int) string {
+ // User might give us bad data. Make sure it's positive and in range.
+ // They'll get nonsense output but it will have the right format.
+ s := strconv.Uitoa(uint(nanosec) % 1e9)
+ // Zero pad left without fmt.
+ if len(s) < 9 {
+ s = "000000000"[:9-len(s)] + s
+ }
+ if n > 9 {
+ n = 9
+ }
+ return "." + s[:n]
+}
+
// Format returns a textual representation of the time value formatted
// according to layout. The layout defines the format by showing the
// representation of a standard time, which is then used to describe
@@ -340,6 +373,10 @@ func (t *Time) Format(layout string) string {
p += zeroPad(zone / 60)
p += zeroPad(zone % 60)
}
+ default:
+ if len(std) >= 2 && std[0:2] == ".0" {
+ p = formatNano(t.Nanosecond, len(std)-1)
+ }
}
b.WriteString(p)
layout = suffix
@@ -355,7 +392,7 @@ func (t *Time) String() string {
return t.Format(UnixDate)
}
-var errBad = os.NewError("bad") // just a marker; not returned to user
+var errBad = os.NewError("bad value for field") // placeholder not passed to user
// ParseError describes a problem parsing a time string.
type ParseError struct {
@@ -620,6 +657,33 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
if offset, found := lookupByName(p); found {
t.ZoneOffset = offset
}
+ default:
+ if len(value) < len(std) {
+ err = errBad
+ break
+ }
+ if len(std) >= 2 && std[0:2] == ".0" {
+ if value[0] != '.' {
+ err = errBad
+ break
+ }
+ t.Nanosecond, err = strconv.Atoi(value[1:len(std)])
+ if err != nil {
+ break
+ }
+ if t.Nanosecond < 0 || t.Nanosecond >= 1e9 {
+ rangeErrString = "fractional second"
+ break
+ }
+ value = value[len(std):]
+ // We need nanoseconds, which means scaling by the number
+ // of missing digits in the format, maximum length 10. If it's
+ // longer than 10, we won't scale.
+ scaleDigits := 10 - len(std)
+ for i := 0; i < scaleDigits; i++ {
+ t.Nanosecond *= 10
+ }
+ }
}
if rangeErrString != "" {
return nil, &ParseError{alayout, avalue, std, value, ": " + rangeErrString + " out of range"}