├── .gitignore ├── LICENSE ├── README.md ├── strftime.go └── strftime_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Jehiah Czebotar 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | go-strftime 2 | =========== 3 | 4 | go implementation of strftime 5 | 6 | ## Example 7 | 8 | ``` 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | "time" 14 | 15 | strftime "github.com/jehiah/go-strftime" 16 | ) 17 | 18 | func main() { 19 | t := time.Unix(1340244776, 0) 20 | utc, _ := time.LoadLocation("UTC") 21 | t = t.In(utc) 22 | fmt.Println(strftime.Format("%Y-%m-%d %H:%M:%S", t)) 23 | // Output: 24 | // 2012-06-21 02:12:56 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /strftime.go: -------------------------------------------------------------------------------- 1 | // go implementation of strftime 2 | package strftime 3 | 4 | import ( 5 | "strings" 6 | "time" 7 | ) 8 | 9 | // taken from time/format.go 10 | var conversion = map[rune]string{ 11 | /*stdLongMonth */ 'B': "January", 12 | /*stdMonth */ 'b': "Jan", 13 | // stdNumMonth */ 'm': "1", 14 | /*stdZeroMonth */ 'm': "01", 15 | /*stdLongWeekDay */ 'A': "Monday", 16 | /*stdWeekDay */ 'a': "Mon", 17 | // stdDay */ 'd': "2", 18 | // stdUnderDay */ 'd': "_2", 19 | /*stdZeroDay */ 'd': "02", 20 | /*stdHour */ 'H': "15", 21 | // stdHour12 */ 'I': "3", 22 | /*stdZeroHour12 */ 'I': "03", 23 | // stdMinute */ 'M': "4", 24 | /*stdZeroMinute */ 'M': "04", 25 | // stdSecond */ 'S': "5", 26 | /*stdZeroSecond */ 'S': "05", 27 | /*stdLongYear */ 'Y': "2006", 28 | /*stdYear */ 'y': "06", 29 | /*stdPM */ 'p': "PM", 30 | // stdpm */ 'p': "pm", 31 | /*stdTZ */ 'Z': "MST", 32 | // stdISO8601TZ */ 'z': "Z0700", // prints Z for UTC 33 | // stdISO8601ColonTZ */ 'z': "Z07:00", // prints Z for UTC 34 | /*stdNumTZ */ 'z': "-0700", // always numeric 35 | // stdNumShortTZ */ 'b': "-07", // always numeric 36 | // stdNumColonTZ */ 'b': "-07:00", // always numeric 37 | /* nonStdMilli */ 'L': ".000", 38 | } 39 | 40 | // This is an alternative to time.Format because no one knows 41 | // what date 040305 is supposed to create when used as a 'layout' string 42 | // this takes standard strftime format options. For a complete list 43 | // of format options see http://strftime.org/ 44 | func Format(format string, t time.Time) string { 45 | retval := make([]byte, 0, len(format)) 46 | for i, ni := 0, 0; i < len(format); i = ni + 2 { 47 | ni = strings.IndexByte(format[i:], '%') 48 | if ni < 0 { 49 | ni = len(format) 50 | } else { 51 | ni += i 52 | } 53 | retval = append(retval, []byte(format[i:ni])...) 54 | if ni+1 < len(format) { 55 | c := format[ni+1] 56 | if c == '%' { 57 | retval = append(retval, '%') 58 | } else { 59 | if layoutCmd, ok := conversion[rune(c)]; ok { 60 | retval = append(retval, []byte(t.Format(layoutCmd))...) 61 | } else { 62 | retval = append(retval, '%', c) 63 | } 64 | } 65 | } else { 66 | if ni < len(format) { 67 | retval = append(retval, '%') 68 | } 69 | } 70 | } 71 | return string(retval) 72 | } 73 | -------------------------------------------------------------------------------- /strftime_test.go: -------------------------------------------------------------------------------- 1 | package strftime 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func ExampleFormat() { 10 | t := time.Unix(1340244776, 0) 11 | utc, _ := time.LoadLocation("UTC") 12 | t = t.In(utc) 13 | fmt.Println(Format("%Y-%m-%d %H:%M:%S", t)) 14 | // Output: 15 | // 2012-06-21 02:12:56 16 | } 17 | 18 | func TestNoLeadingPercentSign(t *testing.T) { 19 | tm := time.Unix(1340244776, 0) 20 | utc, _ := time.LoadLocation("UTC") 21 | tm = tm.In(utc) 22 | result := Format("aaabbb0123456789%Y", tm) 23 | if result != "aaabbb01234567892012" { 24 | t.Logf("%s != %s", result, "aaabbb01234567892012") 25 | t.Fail() 26 | } 27 | } 28 | 29 | func TestUnsupported(t *testing.T) { 30 | tm := time.Unix(1340244776, 0) 31 | utc, _ := time.LoadLocation("UTC") 32 | tm = tm.In(utc) 33 | result := Format("%0%1%%%2", tm) 34 | if result != "%0%1%%2" { 35 | t.Logf("%s != %s", result, "%0%1%%2") 36 | t.Fail() 37 | } 38 | } 39 | 40 | func TestRubyStrftime(t *testing.T) { 41 | tm := time.Unix(1340244776, 0) 42 | utc, _ := time.LoadLocation("UTC") 43 | tm = tm.In(utc) 44 | result := Format("%H:%M:%S%L", tm) 45 | if result != "02:12:56.000" { 46 | t.Logf("%s != %s", result, "02:12:56.000") 47 | t.Fail() 48 | } 49 | } 50 | --------------------------------------------------------------------------------