Split files into smaller parts
parent
84825d48ca
commit
22395c0f3e
42
app_test.go
42
app_test.go
|
@ -1,42 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChooseTemplate(t *testing.T) {
|
||||
tmpl, err := template.New("templates").Funcs(templateFuncs).ParseGlob("templates/*")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
app := &Datetime{tmpl: tmpl}
|
||||
|
||||
type chooseTest struct {
|
||||
accept string
|
||||
acceptable bool
|
||||
contentType string
|
||||
template string
|
||||
}
|
||||
tests := []chooseTest{
|
||||
{"text/html", true, "text/html", "index.html"},
|
||||
{"text/html;q=0.9,text/plain", true, "text/plain", "index.txt"},
|
||||
{"image/png", false, "", ""},
|
||||
{"*/*", true, "text/plain", "index.txt"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
tmpl, contentType, acceptable := app.chooseTemplate(test.accept, "index")
|
||||
fn := fmt.Sprintf("chooseTemplate(\"%s\")", test.accept)
|
||||
if contentType != test.contentType {
|
||||
t.Errorf("%s; contentType = %v; wanted %v", fn, contentType, test.contentType)
|
||||
}
|
||||
if acceptable != test.acceptable {
|
||||
t.Errorf("%s; acceptable = %v; wanted %v", fn, acceptable, test.acceptable)
|
||||
}
|
||||
if tmpl != app.tmpl.Lookup(test.template) {
|
||||
t.Errorf("%s; tmpl = %v; wanted template for %v", fn, tmpl.Name(), test.template)
|
||||
}
|
||||
}
|
||||
}
|
34
template.go
34
template.go
|
@ -7,40 +7,6 @@ import (
|
|||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var templateFuncs = map[string]interface{}{
|
||||
"statusText": templateFuncStatusText,
|
||||
"thisIsSafe": templateFuncThisIsSafe,
|
||||
// Formatting
|
||||
"formatOffset": templateFuncFormatOffset,
|
||||
// Logic
|
||||
"resolveZone": templateFuncResolveZone,
|
||||
}
|
||||
|
||||
func templateFuncStatusText(s int) string {
|
||||
return http.StatusText(s)
|
||||
}
|
||||
func templateFuncThisIsSafe(s string) template.HTML {
|
||||
return template.HTML(s)
|
||||
}
|
||||
|
||||
func templateFuncFormatOffset(offset int) string {
|
||||
return FormatZoneOffset(offset)
|
||||
}
|
||||
|
||||
// ResolvedZone holds a resolved zone or an error
|
||||
type ResolvedZone struct {
|
||||
Zone
|
||||
Error error
|
||||
}
|
||||
|
||||
func templateFuncResolveZone(app Datetime, zone string) ResolvedZone {
|
||||
z, err := ResolveZone(app.cities, zone)
|
||||
if err != nil {
|
||||
l.Debug("unable to resolve zone", zap.Reflect("zone", zone), zap.Error(err))
|
||||
}
|
||||
return ResolvedZone{z, err}
|
||||
}
|
||||
|
||||
// loadTemplate returns a matching template for the request. It also causes an
|
||||
// error if the template is not found or the Accept parameters are incorrect.
|
||||
func (app Datetime) loadTemplate(name string, w http.ResponseWriter, req *http.Request) *template.Template {
|
||||
|
|
|
@ -1,27 +1,42 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTemplateFuncFormatOffset(t *testing.T) {
|
||||
want, got := "+06:06", templateFuncFormatOffset(6*60*60+6*60)
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
func TestChooseTemplate(t *testing.T) {
|
||||
tmpl, err := template.New("templates").Funcs(templateFuncs).ParseGlob("templates/*")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
app := &Datetime{tmpl: tmpl}
|
||||
|
||||
type chooseTest struct {
|
||||
accept string
|
||||
acceptable bool
|
||||
contentType string
|
||||
template string
|
||||
}
|
||||
tests := []chooseTest{
|
||||
{"text/html", true, "text/html", "index.html"},
|
||||
{"text/html;q=0.9,text/plain", true, "text/plain", "index.txt"},
|
||||
{"image/png", false, "", ""},
|
||||
{"*/*", true, "text/plain", "index.txt"},
|
||||
}
|
||||
|
||||
want, got = "-12:15", templateFuncFormatOffset(-(12*60*60 + 15*60))
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
}
|
||||
|
||||
want, got = "\u00B100:00", templateFuncFormatOffset(-(0*60*60 + 0*60))
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
}
|
||||
|
||||
want, got = "+00:01", templateFuncFormatOffset(0*60*60+1*60)
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
for _, test := range tests {
|
||||
tmpl, contentType, acceptable := app.chooseTemplate(test.accept, "index")
|
||||
fn := fmt.Sprintf("chooseTemplate(\"%s\")", test.accept)
|
||||
if contentType != test.contentType {
|
||||
t.Errorf("%s; contentType = %v; wanted %v", fn, contentType, test.contentType)
|
||||
}
|
||||
if acceptable != test.acceptable {
|
||||
t.Errorf("%s; acceptable = %v; wanted %v", fn, acceptable, test.acceptable)
|
||||
}
|
||||
if tmpl != app.tmpl.Lookup(test.template) {
|
||||
t.Errorf("%s; tmpl = %v; wanted template for %v", fn, tmpl.Name(), test.template)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var templateFuncs = map[string]interface{}{
|
||||
"statusText": templateFuncStatusText,
|
||||
"thisIsSafe": templateFuncThisIsSafe,
|
||||
// Formatting
|
||||
"formatOffset": templateFuncFormatOffset,
|
||||
// Logic
|
||||
"resolveZone": templateFuncResolveZone,
|
||||
}
|
||||
|
||||
func templateFuncStatusText(s int) string {
|
||||
return http.StatusText(s)
|
||||
}
|
||||
func templateFuncThisIsSafe(s string) template.HTML {
|
||||
return template.HTML(s)
|
||||
}
|
||||
|
||||
func templateFuncFormatOffset(offset int) string {
|
||||
return FormatZoneOffset(offset)
|
||||
}
|
||||
|
||||
// ResolvedZone holds a resolved zone or an error
|
||||
type ResolvedZone struct {
|
||||
Zone
|
||||
Error error
|
||||
}
|
||||
|
||||
func templateFuncResolveZone(app Datetime, zone string) ResolvedZone {
|
||||
z, err := ResolveZone(app.cities, zone)
|
||||
if err != nil {
|
||||
l.Debug("unable to resolve zone", zap.Reflect("zone", zone), zap.Error(err))
|
||||
}
|
||||
return ResolvedZone{z, err}
|
||||
}
|
64
zone.go
64
zone.go
|
@ -1,76 +1,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/serverwentdown/datetime.link/data"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// ErrZoneNotFound is thrown when a zone string has no match
|
||||
var ErrZoneNotFound = errors.New("zone not found")
|
||||
|
||||
// ErrZoneOffsetInvalid is thrown when a zone string is an invalid zone offset
|
||||
var ErrZoneOffsetInvalid = errors.New("offset zone invalid")
|
||||
|
||||
const zoneHour = 60 * 60
|
||||
const zoneMinute = 60
|
||||
|
||||
var zoneOffsetRegexp = regexp.MustCompile(`^[+-][0-9]{2}:[0-9]{2}$`)
|
||||
|
||||
// SearchCities looks up a city by it's reference
|
||||
func SearchCities(cities map[string]*data.City, city string) (*data.City, error) {
|
||||
// For now, simple map read will do
|
||||
if city, ok := cities[city]; ok {
|
||||
return city, nil
|
||||
}
|
||||
return nil, ErrZoneNotFound
|
||||
}
|
||||
|
||||
// ParseZoneOffset parses a zone string into a time.Location
|
||||
func ParseZoneOffset(zone string) (int, error) {
|
||||
if !zoneOffsetRegexp.MatchString(zone) {
|
||||
return 0, ErrZoneOffsetInvalid
|
||||
}
|
||||
// Assume that if it satisfies the regex, it satisfies the length and won't
|
||||
// fail to parse
|
||||
d := 0
|
||||
if zone[0] == '+' {
|
||||
d = 1
|
||||
}
|
||||
if zone[0] == '-' {
|
||||
d = -1
|
||||
}
|
||||
h, _ := strconv.ParseUint(zone[1:1+2], 10, 64)
|
||||
// Allow hour offsets greater that 24
|
||||
m, _ := strconv.ParseUint(zone[1+3:1+3+2], 10, 64)
|
||||
if m >= 60 {
|
||||
return 0, ErrZoneOffsetInvalid
|
||||
}
|
||||
offset := d * (int(h)*zoneHour + int(m)*zoneMinute)
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
// FormatZoneOffset formats an offset into a string
|
||||
func FormatZoneOffset(offset int) string {
|
||||
neg := offset < 0
|
||||
s := '+'
|
||||
if neg {
|
||||
s = '-'
|
||||
offset = -offset
|
||||
}
|
||||
if offset == 0 {
|
||||
return "\u00B100:00"
|
||||
}
|
||||
h := offset / zoneHour
|
||||
m := (offset % zoneHour) / zoneMinute
|
||||
return fmt.Sprintf("%c%02d:%02d", s, h, m)
|
||||
}
|
||||
|
||||
// Zone represents any form of zone offset: this could be a city or a fixed
|
||||
// offset from UTC
|
||||
type Zone struct {
|
||||
|
|
116
zone_test.go
116
zone_test.go
|
@ -7,104 +7,6 @@ import (
|
|||
"github.com/serverwentdown/datetime.link/data"
|
||||
)
|
||||
|
||||
func TestParseZoneOffset(t *testing.T) {
|
||||
offset, err := ParseZoneOffset("+08:00")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
want := 8*60*60 + 0*60
|
||||
if offset != want {
|
||||
t.Errorf("got %d, want %d", offset, want)
|
||||
}
|
||||
}
|
||||
|
||||
offset, err = ParseZoneOffset("-01:30")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
want := -(1*60*60 + 30*60)
|
||||
if offset != want {
|
||||
t.Errorf("got %d, want %d", offset, want)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("-0030")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("00:30")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("+08:60")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("+08:-6")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
offset, err = ParseZoneOffset("+08:00")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
loc := time.FixedZone("UTC "+FormatZoneOffset(offset), offset)
|
||||
time := time.Date(2020, time.November, 8, 23, 9, 0, 0, loc).Unix()
|
||||
want := int64(1604848140)
|
||||
if time != want {
|
||||
t.Errorf("got %d, want %d", time, want)
|
||||
}
|
||||
}
|
||||
|
||||
offset, err = ParseZoneOffset("-00:30")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
loc := time.FixedZone("UTC "+FormatZoneOffset(offset), offset)
|
||||
time := time.Date(2020, time.November, 8, 14, 39, 0, 0, loc).Unix()
|
||||
want := int64(1604848140)
|
||||
if time != want {
|
||||
t.Errorf("got %d, want %d", time, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchCities(t *testing.T) {
|
||||
cities, err := data.ReadCities()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
city, err := SearchCities(cities, "Singapore-SG")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
}
|
||||
wantName := "Singapore"
|
||||
wantZone := "Asia/Singapore"
|
||||
if city.Name != wantName || city.Timezone != wantZone {
|
||||
t.Errorf("want %v %v, got %v", wantName, wantZone, city)
|
||||
}
|
||||
|
||||
city, err = SearchCities(cities, "Yuzhno_Sakhalinsk-Sakhalin_Oblast-RU")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
}
|
||||
wantName = "Yuzhno-Sakhalinsk"
|
||||
wantZone = "Asia/Sakhalin"
|
||||
if city.Name != wantName || city.Timezone != wantZone {
|
||||
t.Errorf("want %v %v, got %v", wantName, wantZone, city)
|
||||
}
|
||||
|
||||
_, err = SearchCities(cities, "Nowhere")
|
||||
if err != ErrZoneNotFound {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneNotFound, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveZone(t *testing.T) {
|
||||
cities, err := data.ReadCities()
|
||||
if err != nil {
|
||||
|
@ -147,21 +49,3 @@ func TestResolveZone(t *testing.T) {
|
|||
t.Errorf("want error %v, got error %v", ErrZoneNotFound, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReadCities(b *testing.B) {
|
||||
// This does take quite a while
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = data.ReadCities()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSearchCities(b *testing.B) {
|
||||
cities, err := data.ReadCities()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = SearchCities(cities, "Yuzhno_Sakhalinsk-Sakhalin_Oblast-RU")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/serverwentdown/datetime.link/data"
|
||||
)
|
||||
|
||||
// ErrZoneNotFound is thrown when a zone string has no match
|
||||
var ErrZoneNotFound = errors.New("zone not found")
|
||||
|
||||
// SearchCities looks up a city by it's reference
|
||||
func SearchCities(cities map[string]*data.City, city string) (*data.City, error) {
|
||||
// For now, simple map read will do
|
||||
if city, ok := cities[city]; ok {
|
||||
return city, nil
|
||||
}
|
||||
return nil, ErrZoneNotFound
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/serverwentdown/datetime.link/data"
|
||||
)
|
||||
|
||||
func TestSearchCities(t *testing.T) {
|
||||
cities, err := data.ReadCities()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
city, err := SearchCities(cities, "Singapore-SG")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
}
|
||||
wantName := "Singapore"
|
||||
wantZone := "Asia/Singapore"
|
||||
if city.Name != wantName || city.Timezone != wantZone {
|
||||
t.Errorf("want %v %v, got %v", wantName, wantZone, city)
|
||||
}
|
||||
|
||||
city, err = SearchCities(cities, "Yuzhno_Sakhalinsk-Sakhalin_Oblast-RU")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
}
|
||||
wantName = "Yuzhno-Sakhalinsk"
|
||||
wantZone = "Asia/Sakhalin"
|
||||
if city.Name != wantName || city.Timezone != wantZone {
|
||||
t.Errorf("want %v %v, got %v", wantName, wantZone, city)
|
||||
}
|
||||
|
||||
_, err = SearchCities(cities, "Nowhere")
|
||||
if err != ErrZoneNotFound {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneNotFound, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReadCities(b *testing.B) {
|
||||
// This does take quite a while
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = data.ReadCities()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSearchCities(b *testing.B) {
|
||||
cities, err := data.ReadCities()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = SearchCities(cities, "Yuzhno_Sakhalinsk-Sakhalin_Oblast-RU")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ErrZoneOffsetInvalid is thrown when a zone string is an invalid zone offset
|
||||
var ErrZoneOffsetInvalid = errors.New("offset zone invalid")
|
||||
|
||||
const zoneHour = 60 * 60
|
||||
const zoneMinute = 60
|
||||
|
||||
var zoneOffsetRegexp = regexp.MustCompile(`^[+-][0-9]{2}:[0-9]{2}$`)
|
||||
|
||||
// ParseZoneOffset parses a zone string into an offset
|
||||
func ParseZoneOffset(zone string) (int, error) {
|
||||
if !zoneOffsetRegexp.MatchString(zone) {
|
||||
return 0, ErrZoneOffsetInvalid
|
||||
}
|
||||
// Assume that if it satisfies the regex, it satisfies the length and won't
|
||||
// fail to parse
|
||||
d := 0
|
||||
if zone[0] == '+' {
|
||||
d = 1
|
||||
}
|
||||
if zone[0] == '-' {
|
||||
d = -1
|
||||
}
|
||||
h, _ := strconv.ParseUint(zone[1:1+2], 10, 64)
|
||||
// Allow hour offsets greater that 24
|
||||
m, _ := strconv.ParseUint(zone[1+3:1+3+2], 10, 64)
|
||||
if m >= 60 {
|
||||
return 0, ErrZoneOffsetInvalid
|
||||
}
|
||||
offset := d * (int(h)*zoneHour + int(m)*zoneMinute)
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
// FormatZoneOffset formats an offset into a string
|
||||
func FormatZoneOffset(offset int) string {
|
||||
neg := offset < 0
|
||||
s := '+'
|
||||
if neg {
|
||||
s = '-'
|
||||
offset = -offset
|
||||
}
|
||||
if offset == 0 {
|
||||
return "\u00B100:00"
|
||||
}
|
||||
h := offset / zoneHour
|
||||
m := (offset % zoneHour) / zoneMinute
|
||||
return fmt.Sprintf("%c%02d:%02d", s, h, m)
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestParseZoneOffset(t *testing.T) {
|
||||
offset, err := ParseZoneOffset("+08:00")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
want := 8*60*60 + 0*60
|
||||
if offset != want {
|
||||
t.Errorf("got %d, want %d", offset, want)
|
||||
}
|
||||
}
|
||||
|
||||
offset, err = ParseZoneOffset("-01:30")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
want := -(1*60*60 + 30*60)
|
||||
if offset != want {
|
||||
t.Errorf("got %d, want %d", offset, want)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("-0030")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("00:30")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("+08:60")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
_, err = ParseZoneOffset("+08:-6")
|
||||
if err != ErrZoneOffsetInvalid {
|
||||
t.Errorf("want error %v, got error %v", ErrZoneOffsetInvalid, err)
|
||||
}
|
||||
|
||||
offset, err = ParseZoneOffset("+08:00")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
loc := time.FixedZone("UTC "+FormatZoneOffset(offset), offset)
|
||||
time := time.Date(2020, time.November, 8, 23, 9, 0, 0, loc).Unix()
|
||||
want := int64(1604848140)
|
||||
if time != want {
|
||||
t.Errorf("got %d, want %d", time, want)
|
||||
}
|
||||
}
|
||||
|
||||
offset, err = ParseZoneOffset("-00:30")
|
||||
if err != nil {
|
||||
t.Errorf("want error %v, got error %v", nil, err)
|
||||
} else {
|
||||
loc := time.FixedZone("UTC "+FormatZoneOffset(offset), offset)
|
||||
time := time.Date(2020, time.November, 8, 14, 39, 0, 0, loc).Unix()
|
||||
want := int64(1604848140)
|
||||
if time != want {
|
||||
t.Errorf("got %d, want %d", time, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatZoneOffset(t *testing.T) {
|
||||
want, got := "+06:06", FormatZoneOffset(6*60*60+6*60)
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
}
|
||||
|
||||
want, got = "-12:15", FormatZoneOffset(-(12*60*60 + 15*60))
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
}
|
||||
|
||||
want, got = "\u00B100:00", FormatZoneOffset(-(0*60*60 + 0*60))
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
}
|
||||
|
||||
want, got = "+00:01", FormatZoneOffset(0*60*60+1*60)
|
||||
if want != got {
|
||||
t.Fatalf("got offset %v, want offset %v", got, want)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue