summaryrefslogtreecommitdiff
path: root/src/pkg/time/time.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/time/time.go')
-rw-r--r--src/pkg/time/time.go372
1 files changed, 372 insertions, 0 deletions
diff --git a/src/pkg/time/time.go b/src/pkg/time/time.go
new file mode 100644
index 000000000..ea9b66cbc
--- /dev/null
+++ b/src/pkg/time/time.go
@@ -0,0 +1,372 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The time package provides functionality for measuring and
+// displaying time.
+package time
+
+import (
+ "os";
+ "time"
+)
+
+// Seconds reports the number of seconds since the Unix epoch,
+// January 1, 1970 00:00:00 UTC.
+func Seconds() int64 {
+ sec, nsec, err := os.Time();
+ if err != nil {
+ panic("time: os.Time: ", err.String());
+ }
+ return sec
+}
+
+// Nanoseconds reports the number of nanoseconds since the Unix epoch,
+// January 1, 1970 00:00:00 UTC.
+func Nanoseconds() int64 {
+ sec, nsec, err := os.Time();
+ if err != nil {
+ panic("time: os.Time: ", err.String());
+ }
+ return sec*1e9 + nsec
+}
+
+// Days of the week.
+const (
+ Sunday = iota;
+ Monday;
+ Tuesday;
+ Wednesday;
+ Thursday;
+ Friday;
+ Saturday;
+)
+
+// Time is the struct representing a parsed time value.
+type Time struct {
+ Year int64; // 2008 is 2008
+ Month, Day int; // Sep-17 is 9, 17
+ Hour, Minute, Second int; // 10:43:12 is 10, 43, 12
+ Weekday int; // Sunday, Monday, ...
+ ZoneOffset int; // seconds west of UTC
+ Zone string;
+}
+
+var nonleapyear = []int{
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+}
+var leapyear = []int{
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+}
+
+func months(year int64) []int {
+ if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
+ return leapyear
+ }
+ return nonleapyear
+}
+
+const (
+ secondsPerDay = 24*60*60;
+
+ daysPer400Years = 365*400+97;
+ daysPer100Years = 365*100+24;
+ daysPer4Years = 365*4+1;
+
+ days1970To2001 = 31*365+8;
+)
+
+// SecondsToUTC converts sec, in number of seconds since the Unix epoch,
+// into a parsed Time value in the UTC time zone.
+func SecondsToUTC(sec int64) *Time {
+ t := new(Time);
+
+ // Split into time and day.
+ day := sec/secondsPerDay;
+ sec -= day*secondsPerDay;
+ if sec < 0 {
+ day--;
+ sec += secondsPerDay
+ }
+
+ // Time
+ t.Hour = int(sec/3600);
+ t.Minute = int((sec/60)%60);
+ t.Second = int(sec%60);
+
+ // Day 0 = January 1, 1970 was a Thursday
+ t.Weekday = int((day + Thursday) % 7);
+ if t.Weekday < 0 {
+ t.Weekday += 7
+ }
+
+ // Change day from 0 = 1970 to 0 = 2001,
+ // to make leap year calculations easier
+ // (2001 begins 4-, 100-, and 400-year cycles ending in a leap year.)
+ day -= days1970To2001;
+
+ year := int64(2001);
+ if day < 0 {
+ // Go back enough 400 year cycles to make day positive.
+ n := -day/daysPer400Years + 1;
+ year -= 400*n;
+ day += daysPer400Years*n;
+ } else {
+ // Cut off 400 year cycles.
+ n := day/daysPer400Years;
+ year += 400*n;
+ day -= daysPer400Years*n;
+ }
+
+ // Cut off 100-year cycles
+ n := day/daysPer100Years;
+ year += 100*n;
+ day -= daysPer100Years*n;
+
+ // Cut off 4-year cycles
+ n = day/daysPer4Years;
+ year += 4*n;
+ day -= daysPer4Years*n;
+
+ // Cut off non-leap years.
+ n = day/365;
+ year += n;
+ day -= 365*n;
+
+ t.Year = year;
+
+ // If someone ever needs yearday,
+ // tyearday = day (+1?)
+
+ months := months(year);
+ var m int;
+ yday := int(day);
+ for m = 0; m < 12 && yday >= months[m]; m++ {
+ yday -= months[m]
+ }
+ t.Month = m+1;
+ t.Day = yday+1;
+ t.Zone = "UTC";
+
+ return t;
+}
+
+// UTC returns the current time as a parsed Time value in the UTC time zone.
+func UTC() *Time {
+ return SecondsToUTC(Seconds())
+}
+
+// SecondsToLocalTime converts sec, in number of seconds since the Unix epoch,
+// into a parsed Time value in the local time zone.
+func SecondsToLocalTime(sec int64) *Time {
+ z, offset, err := time.lookupTimezone(sec);
+ if err != nil {
+ return SecondsToUTC(sec)
+ }
+ t := SecondsToUTC(sec+int64(offset));
+ t.Zone = z;
+ t.ZoneOffset = offset;
+ return t
+}
+
+// LocalTime returns the current time as a parsed Time value in the local time zone.
+func LocalTime() *Time {
+ return SecondsToLocalTime(Seconds())
+}
+
+// Seconds returns the number of seconds since January 1, 1970 represented by the
+// parsed Time value.
+func (t *Time) Seconds() int64 {
+ // First, accumulate days since January 1, 2001.
+ // Using 2001 instead of 1970 makes the leap-year
+ // handling easier (see SecondsToUTC), because
+ // it is at the beginning of the 4-, 100-, and 400-year cycles.
+ day := int64(0);
+
+ // Rewrite year to be >= 2001.
+ year := t.Year;
+ if year < 2001 {
+ n := (2001 - year)/400 + 1;
+ year += 400*n;
+ day -= daysPer400Years*n;
+ }
+
+ // Add in days from 400-year cycles.
+ n := (year - 2001) / 400;
+ year -= 400*n;
+ day += daysPer400Years*n;
+
+ // Add in 100-year cycles.
+ n = (year - 2001) / 100;
+ year -= 100*n;
+ day += daysPer100Years*n;
+
+ // Add in 4-year cycles.
+ n = (year - 2001) / 4;
+ year -= 4*n;
+ day += daysPer4Years*n;
+
+ // Add in non-leap years.
+ n = year - 2001;
+ day += 365*n;
+
+ // Add in days this year.
+ months := months(t.Year);
+ for m := 0; m < t.Month-1; m++ {
+ day += int64(months[m])
+ }
+ day += int64(t.Day - 1);
+
+ // Convert days to seconds since January 1, 2001.
+ sec := day * secondsPerDay;
+
+ // Add in time elapsed today.
+ sec += int64(t.Hour) * 3600;
+ sec += int64(t.Minute) * 60;
+ sec += int64(t.Second);
+
+ // Convert from seconds since 2001 to seconds since 1970.
+ sec += days1970To2001 * secondsPerDay;
+
+ // Account for local time zone.
+ sec -= int64(t.ZoneOffset);
+ return sec
+}
+
+var longDayNames = []string{
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+}
+
+var shortDayNames = []string{
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+}
+
+var shortMonthNames = []string{
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+}
+
+func copy(dst []byte, s string) {
+ for i := 0; i < len(s); i++ {
+ dst[i] = s[i]
+ }
+}
+
+func decimal(dst []byte, n int) {
+ if n < 0 {
+ n = 0
+ }
+ for i := len(dst)-1; i >= 0; i-- {
+ dst[i] = byte(n%10 + '0');
+ n /= 10
+ }
+}
+
+func addString(buf []byte, bp int, s string) int {
+ n := len(s);
+ copy(buf[bp:bp+n], s);
+ return bp+n
+}
+
+// Just enough of strftime to implement the date formats below.
+// Not exported.
+func format(t *Time, fmt string) string {
+ buf := make([]byte, 128);
+ bp := 0;
+
+ for i := 0; i < len(fmt); i++ {
+ if fmt[i] == '%' {
+ i++;
+ switch fmt[i] {
+ case 'A': // %A full weekday name
+ bp = addString(buf, bp, longDayNames[t.Weekday]);
+ case 'a': // %a abbreviated weekday name
+ bp = addString(buf, bp, shortDayNames[t.Weekday]);
+ case 'b': // %b abbreviated month name
+ bp = addString(buf, bp, shortMonthNames[t.Month-1]);
+ case 'd': // %d day of month (01-31)
+ decimal(buf[bp:bp+2], t.Day);
+ bp += 2;
+ case 'e': // %e day of month ( 1-31)
+ if t.Day >= 10 {
+ decimal(buf[bp:bp+2], t.Day)
+ } else {
+ buf[bp] = ' ';
+ buf[bp+1] = byte(t.Day + '0')
+ }
+ bp += 2;
+ case 'H': // %H hour 00-23
+ decimal(buf[bp:bp+2], t.Hour);
+ bp += 2;
+ case 'M': // %M minute 00-59
+ decimal(buf[bp:bp+2], t.Minute);
+ bp += 2;
+ case 'S': // %S second 00-59
+ decimal(buf[bp:bp+2], t.Second);
+ bp += 2;
+ case 'Y': // %Y year 2008
+ decimal(buf[bp:bp+4], int(t.Year));
+ bp += 4;
+ case 'y': // %y year 08
+ decimal(buf[bp:bp+2], int(t.Year%100));
+ bp += 2;
+ case 'Z':
+ bp = addString(buf, bp, t.Zone);
+ default:
+ buf[bp] = '%';
+ buf[bp+1] = fmt[i];
+ bp += 2
+ }
+ } else {
+ buf[bp] = fmt[i];
+ bp++;
+ }
+ }
+ return string(buf[0:bp])
+}
+
+// Asctime formats the parsed time value in the style of
+// ANSI C asctime: Sun Nov 6 08:49:37 1994
+func (t *Time) Asctime() string {
+ return format(t, "%a %b %e %H:%M:%S %Y")
+}
+
+// RFC850 formats the parsed time value in the style of
+// RFC 850: Sunday, 06-Nov-94 08:49:37 UTC
+func (t *Time) RFC850() string {
+ return format(t, "%A, %d-%b-%y %H:%M:%S %Z")
+}
+
+// RFC1123 formats the parsed time value in the style of
+// RFC 1123: Sun, 06 Nov 1994 08:49:37 UTC
+func (t *Time) RFC1123() string {
+ return format(t, "%a, %d %b %Y %H:%M:%S %Z")
+}
+
+// String formats the parsed time value in the style of
+// date(1) - Sun Nov 6 08:49:37 UTC 1994
+func (t *Time) String() string {
+ return format(t, "%a %b %e %H:%M:%S %Z %Y")
+}