1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
|
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"strconv"
"time"
)
var (
format = "2006-01-02 15:04" // Format that will be used for times.
outFormat = format + " MST" // Output format.
tz = "Local" // String descriptor for timezone.
fromLoc *time.Location = time.Local // Go time.Location for the named timezone.
fromUnix bool // Input times are Unix timestamps.
toLoc *time.Location = time.UTC // Go time.Location for output timezone.
)
func usage(w io.Writer) {
fmt.Fprintf(w, `Usage: utc [-f format] [-o format] [-q] [-t] [-u] [-z zone] [time(s)...]
utc -h | utc help
utc converts times to UTC. If no arguments are provided, prints the
current time in UTC. If the only argument provided is "-", utc reads
newline-separated timestamps from standard input. If the argument is
"help", it will print an extended help message with examples. If both
the input and output timezones are the same (e.g., the local time zone
is UTC), a warning message will be printed on standard error. This can
be suppressed with the -q option.
Flags:
-f format Go timestamp format for input times. See the Go docs
(e.g. https://golang.org/pkg/time/#pkg-constants)
for an explanation of this format.
Default value: %s
-h Print this help message.
-o format Go timestamp format for outputting times.
It uses the same format as the '-f' argument.
Default value: %s
-q Suppress the timezone check warning message.
-t Input times are Unix timestamps. Use with
-u to convert the timestamp to the timezone
specified by the -z option (which defaults
to %s).
-u Timestamps are in UTC format and should be
converted to the timezone specified by the
-z argument (which defaults to '%s'). Note
that this isn't particularly useful with
no arguments.
-z zone Text form of the time zone; this can be in short
time zone abbreviation (e.g. MST) or a
location (e.g. America/Los_Angeles). This
has no effect when printing the current
time.
Default value: %s
`, format, outFormat, tz, tz, tz)
}
func usageExamples() {
usage(os.Stdout)
fmt.Println(`
Examples (note that the examples are done in the America/Los_Angeles /
PST8PDT time zone):
+ Getting the current time in UTC:
$ utc
2016-06-14 14:30 PDT = 2016-06-14 21:30 UTC
+ Converting a local timestamp to UTC:
$ utc '2016-06-14 21:30'
2016-06-14 21:30 PDT = 2016-06-15 04:30 UTC
+ Converting a local EST timestamp to UTC (on a machine set to
PST8PDT):
$ utc -z EST '2016-06-14 21:30'
2016-06-14 21:30 EST = 2016-06-15 02:30 UTC
+ Converting timestamps in the form '14-06-2016 3:04PM':
$ utc -f '02-01-2006 3:04PM' '14-06-2016 9:30PM'
2016-06-14 21:30 PDT = 2016-06-15 04:30 UTC
+ Converting timestamps from standard input:
$ printf "2016-06-14 14:42\n2016-06-13 11:01" | utc -
2016-06-14 14:42 PDT = 2016-06-14 21:42 UTC
2016-06-13 11:01 PDT = 2016-06-13 18:01 UTC
+ Converting a UTC timestamp to the local time zone:
$ utc -u '2016-06-14 21:30'
2016-06-14 21:30 UTC = 2016-06-14 14:30 PDT
+ Converting a UTC timestamp to EST (on a machine set to
PST8PDT):
$ utc -u -z EST '2016-06-14 21:30'
2016-06-14 21:30 UTC = 2016-06-14 16:30 EST
+ Using a different output format:
$ utc -o '2006-01-02T15:03:04-0700' '2016-06-14 21:30'
2016-06-14T21:09:30-0700 = 2016-06-15T04:04:30+0000
+ Converting a Unix timestamp to a UTC time:
$ utc -t 1466052938
2016-06-15 21:55 PDT = 2016-06-16 04:55 UTC
+ Converting a Unix timestamp to local time:
$ utc -t -u 1466052938
2016-06-16 04:55 UTC = 2016-06-15 21:55 PDT
+ Converting a Unix timestamp to EST:
$ utc -t -u -z EST 1466052938
2016-06-16 04:55 UTC = 2016-06-15 23:55 EST
+ Example of the warning message when running utc on a machine
where the local time zone is UTC:
$ utc
==================================================================
Note: both input and output timezone offsets are the same --- this
program may not do what you expect it to.
(Converting from UTC (offset +0000) to UTC (offset +0000).)
==================================================================
2016-06-14 23:44 = 2016-06-14 23:44
+ Example of the warning message when running utc on a machine
where the local time zone is GMT:
$ utc
==================================================================
Note: both input and output timezone offsets are the same --- this
program may not do what you expect it to.
(Converting from GMT (offset +0000) to UTC (offset +0000).)
==================================================================
2016-06-14 23:46 = 2016-06-14 23:46
`)
}
func getZone(loc *time.Location) (string, int) {
return time.Now().In(loc).Zone()
}
func checkZones(quiet bool) {
if quiet {
return
}
toZone, toOff := getZone(toLoc)
fromZone, fromOff := getZone(fromLoc)
if toOff == fromOff {
fmt.Fprintf(os.Stderr, `
==================================================================
Note: both input and output timezone offsets are the same --- this
program may not do what you expect it to.
(Converting from %s (offset %+05d) to %s (offset %+05d).)
==================================================================
`, fromZone, fromOff, toZone, toOff)
}
}
func init() {
var help, quiet, utc bool
flag.Usage = func() { usage(os.Stderr) }
flag.StringVar(&format, "f", format, "time format")
flag.BoolVar(&help, "h", false, "print usage information")
flag.StringVar(&outFormat, "o", outFormat, "output time format")
flag.BoolVar(&quiet, "q", false, "suppress zone check warning")
flag.BoolVar(&fromUnix, "t", false, "input times are Unix timestamps")
flag.BoolVar(&utc, "u", false, "timestamps are in UTC format")
flag.StringVar(&tz, "z", tz, "time zone to convert from; if blank, the local timezone is used")
flag.Parse()
if help {
if !utc {
checkZones(quiet)
}
usage(os.Stdout)
os.Exit(0)
}
if utc {
var err error
toLoc, err = time.LoadLocation(tz)
if err != nil {
fmt.Fprintf(os.Stderr, "Malformed timezone %s: %s\n", tz, err)
os.Exit(1)
}
fromLoc = time.UTC
} else {
var err error
fromLoc, err = time.LoadLocation(tz)
if err != nil {
fmt.Fprintf(os.Stderr, "Malformed timezone %s: %s\n", tz, err)
os.Exit(1)
}
if fromLoc == time.UTC {
}
toLoc = time.UTC
}
checkZones(quiet)
}
func showTime(t time.Time) {
fmt.Printf("%s = %s\n", t.Format(outFormat),
t.In(toLoc).Format(outFormat))
}
func parseTime(in string) (time.Time, error) {
if !fromUnix {
return time.ParseInLocation(format, in, fromLoc)
}
var t time.Time
n, err := strconv.ParseInt(in, 10, 64)
if err != nil {
return t, err
}
t = time.Unix(n, 0).In(fromLoc)
return t, nil
}
func dumpTimes(times []string) bool {
var errored bool
for _, t := range times {
u, err := parseTime(t)
if err != nil {
errored = true
fmt.Fprintf(os.Stderr, "Malformed time %s: %s\n", t, err)
continue
}
showTime(u)
}
return errored
}
func main() {
var times []string
n := flag.NArg()
switch n {
case 0:
showTime(time.Now())
os.Exit(0)
case 1:
if flag.Arg(0) == "-" {
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
times = append(times, s.Text())
}
} else if flag.Arg(0) == "help" {
usageExamples()
} else {
times = flag.Args()
}
default:
times = flag.Args()
}
if dumpTimes(times) {
os.Exit(1)
}
}
|