diff --git a/net/ghttp/ghttp_request.go b/net/ghttp/ghttp_request.go index 20daacdd2..dd7ccaece 100644 --- a/net/ghttp/ghttp_request.go +++ b/net/ghttp/ghttp_request.go @@ -37,10 +37,14 @@ type Request struct { hasHookHandler bool // 是否检索到钩子函数(用于请求时提高钩子函数功能启用判断效率) hasServeHandler bool // 是否检索到服务函数 parsedGet bool // GET参数是否已经解析 + parsedPut bool // PUT参数是否已经解析 parsedPost bool // POST参数是否已经解析 + parsedDelete bool // DELETE参数是否已经解析 parsedRaw bool // 原始参数是否已经解析 getMap map[string]interface{} // GET解析参数 + putMap map[string]interface{} // PUT解析参数 postMap map[string]interface{} // POST解析参数 + deleteMap map[string]interface{} // DELETE解析参数 routerMap map[string]interface{} // 路由解析参数 rawVarMap map[string]interface{} // 原始数据参数 error error // 当前请求执行错误 diff --git a/net/ghttp/ghttp_request_method_delete.go b/net/ghttp/ghttp_request_method_delete.go new file mode 100644 index 000000000..ca5b0ad36 --- /dev/null +++ b/net/ghttp/ghttp_request_method_delete.go @@ -0,0 +1,149 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package ghttp + +import ( + "strings" + + "github.com/gogf/gf/container/gvar" + "github.com/gogf/gf/internal/structs" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" +) + +func (r *Request) initDelete() { + if !r.parsedDelete { + r.parsedDelete = true + if strings.EqualFold(r.Method, "DELETE") { + r.parsedRaw = true + if raw := r.GetRawString(); len(raw) > 0 { + r.deleteMap, _ = gstr.Parse(raw) + } + } + } + if r.deleteMap == nil { + r.deleteMap = make(map[string]interface{}) + } +} + +func (r *Request) SetDelete(key string, value interface{}) { + r.initDelete() + r.deleteMap[key] = value +} + +func (r *Request) GetDelete(key string, def ...interface{}) interface{} { + r.initDelete() + if v, ok := r.deleteMap[key]; ok { + return v + } + if len(def) > 0 { + return def[0] + } + return nil +} + +func (r *Request) GetDeleteVar(key string, def ...interface{}) *gvar.Var { + return gvar.New(r.GetDelete(key, def...)) +} + +func (r *Request) GetDeleteString(key string, def ...interface{}) string { + return r.GetDeleteVar(key, def...).String() +} + +func (r *Request) GetDeleteBool(key string, def ...interface{}) bool { + return r.GetDeleteVar(key, def...).Bool() +} + +func (r *Request) GetDeleteInt(key string, def ...interface{}) int { + return r.GetDeleteVar(key, def...).Int() +} + +func (r *Request) GetDeleteInts(key string, def ...interface{}) []int { + return r.GetDeleteVar(key, def...).Ints() +} + +func (r *Request) GetDeleteUint(key string, def ...interface{}) uint { + return r.GetDeleteVar(key, def...).Uint() +} + +func (r *Request) GetDeleteFloat32(key string, def ...interface{}) float32 { + return r.GetDeleteVar(key, def...).Float32() +} + +func (r *Request) GetDeleteFloat64(key string, def ...interface{}) float64 { + return r.GetDeleteVar(key, def...).Float64() +} + +func (r *Request) GetDeleteFloats(key string, def ...interface{}) []float64 { + return r.GetDeleteVar(key, def...).Floats() +} + +func (r *Request) GetDeleteArray(key string, def ...interface{}) []string { + return r.GetDeleteVar(key, def...).Strings() +} + +func (r *Request) GetDeleteStrings(key string, def ...interface{}) []string { + return r.GetDeleteVar(key, def...).Strings() +} + +func (r *Request) GetDeleteInterfaces(key string, def ...interface{}) []interface{} { + return r.GetDeleteVar(key, def...).Interfaces() +} + +// 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值。 +// 当不指定键值对关联数组时,默认获取POST方式提交的所有的提交键值对数据。 +func (r *Request) GetDeleteMap(kvMap ...map[string]interface{}) map[string]interface{} { + r.initDelete() + if len(kvMap) > 0 { + m := make(map[string]interface{}) + for k, defValue := range kvMap[0] { + if deleteValue, ok := r.deleteMap[k]; ok { + m[k] = deleteValue + } else { + m[k] = defValue + } + } + return m + } else { + return r.deleteMap + } +} + +func (r *Request) GetDeleteMapStrStr(kvMap ...map[string]interface{}) map[string]string { + deleteMap := r.GetDeleteMap(kvMap...) + if len(deleteMap) > 0 { + m := make(map[string]string) + for k, v := range deleteMap { + m[k] = gconv.String(v) + } + return m + } + return nil +} + +func (r *Request) GetDeleteMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var { + deleteMap := r.GetDeleteMap(kvMap...) + if len(deleteMap) > 0 { + m := make(map[string]*gvar.Var) + for k, v := range deleteMap { + m[k] = gvar.New(v) + } + return m + } + return nil +} + +func (r *Request) GetDeleteToStruct(pointer interface{}, mapping ...map[string]string) error { + r.initDelete() + tagMap := structs.TagMapName(pointer, paramTagPriority, true) + if len(mapping) > 0 { + for k, v := range mapping[0] { + tagMap[k] = v + } + } + return gconv.StructDeep(r.deleteMap, pointer, tagMap) +} diff --git a/net/ghttp/ghttp_request_post.go b/net/ghttp/ghttp_request_method_post.go similarity index 95% rename from net/ghttp/ghttp_request_post.go rename to net/ghttp/ghttp_request_method_post.go index 204e51ebb..63f06e487 100644 --- a/net/ghttp/ghttp_request_post.go +++ b/net/ghttp/ghttp_request_method_post.go @@ -17,7 +17,6 @@ import ( "github.com/gogf/gf/util/gconv" ) -// 初始化POST请求参数 func (r *Request) initPost() { if !r.parsedPost { r.parsedPost = true @@ -64,7 +63,6 @@ func (r *Request) initPost() { } } -// 设置当前请求的POST参数 func (r *Request) SetPost(key string, value interface{}) { r.initPost() r.postMap[key] = value @@ -172,7 +170,6 @@ func (r *Request) GetPostMapStrVar(kvMap ...map[string]interface{}) map[string]* return nil } -// 将所有的request参数映射到struct属性上,参数object应当为一个struct对象的指针, mapping为非必需参数,自定义参数与属性的映射关系 func (r *Request) GetPostToStruct(pointer interface{}, mapping ...map[string]string) error { r.initPost() tagMap := structs.TagMapName(pointer, paramTagPriority, true) diff --git a/net/ghttp/ghttp_request_method_put.go b/net/ghttp/ghttp_request_method_put.go new file mode 100644 index 000000000..fb270aa71 --- /dev/null +++ b/net/ghttp/ghttp_request_method_put.go @@ -0,0 +1,148 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package ghttp + +import ( + "github.com/gogf/gf/container/gvar" + "github.com/gogf/gf/internal/structs" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" + "strings" +) + +func (r *Request) initPut() { + if !r.parsedPut { + r.parsedPut = true + if strings.EqualFold(r.Method, "PUT") { + r.parsedRaw = true + if raw := r.GetRawString(); len(raw) > 0 { + r.putMap, _ = gstr.Parse(raw) + } + } + } + if r.putMap == nil { + r.putMap = make(map[string]interface{}) + } +} + +func (r *Request) SetPut(key string, value interface{}) { + r.initPut() + r.putMap[key] = value +} + +func (r *Request) GetPut(key string, def ...interface{}) interface{} { + r.initPut() + if v, ok := r.putMap[key]; ok { + return v + } + if len(def) > 0 { + return def[0] + } + return nil +} + +func (r *Request) GetPutVar(key string, def ...interface{}) *gvar.Var { + return gvar.New(r.GetPut(key, def...)) +} + +func (r *Request) GetPutString(key string, def ...interface{}) string { + return r.GetPutVar(key, def...).String() +} + +func (r *Request) GetPutBool(key string, def ...interface{}) bool { + return r.GetPutVar(key, def...).Bool() +} + +func (r *Request) GetPutInt(key string, def ...interface{}) int { + return r.GetPutVar(key, def...).Int() +} + +func (r *Request) GetPutInts(key string, def ...interface{}) []int { + return r.GetPutVar(key, def...).Ints() +} + +func (r *Request) GetPutUint(key string, def ...interface{}) uint { + return r.GetPutVar(key, def...).Uint() +} + +func (r *Request) GetPutFloat32(key string, def ...interface{}) float32 { + return r.GetPutVar(key, def...).Float32() +} + +func (r *Request) GetPutFloat64(key string, def ...interface{}) float64 { + return r.GetPutVar(key, def...).Float64() +} + +func (r *Request) GetPutFloats(key string, def ...interface{}) []float64 { + return r.GetPutVar(key, def...).Floats() +} + +func (r *Request) GetPutArray(key string, def ...interface{}) []string { + return r.GetPutVar(key, def...).Strings() +} + +func (r *Request) GetPutStrings(key string, def ...interface{}) []string { + return r.GetPutVar(key, def...).Strings() +} + +func (r *Request) GetPutInterfaces(key string, def ...interface{}) []interface{} { + return r.GetPutVar(key, def...).Interfaces() +} + +// 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值。 +// 当不指定键值对关联数组时,默认获取POST方式提交的所有的提交键值对数据。 +func (r *Request) GetPutMap(kvMap ...map[string]interface{}) map[string]interface{} { + r.initPut() + if len(kvMap) > 0 { + m := make(map[string]interface{}) + for k, defValue := range kvMap[0] { + if putValue, ok := r.putMap[k]; ok { + m[k] = putValue + } else { + m[k] = defValue + } + } + return m + } else { + return r.putMap + } +} + +func (r *Request) GetPutMapStrStr(kvMap ...map[string]interface{}) map[string]string { + putMap := r.GetPutMap(kvMap...) + if len(putMap) > 0 { + m := make(map[string]string) + for k, v := range putMap { + m[k] = gconv.String(v) + } + return m + } + return nil +} + +func (r *Request) GetPutMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var { + putMap := r.GetPutMap(kvMap...) + if len(putMap) > 0 { + m := make(map[string]*gvar.Var) + for k, v := range putMap { + m[k] = gvar.New(v) + } + return m + } + return nil +} + +func (r *Request) GetPutToStruct(pointer interface{}, mapping ...map[string]string) error { + r.initPut() + tagMap := structs.TagMapName(pointer, paramTagPriority, true) + if len(mapping) > 0 { + for k, v := range mapping[0] { + tagMap[k] = v + } + } + return gconv.StructDeep(r.putMap, pointer, tagMap) +} diff --git a/net/ghttp/ghttp_request_query.go b/net/ghttp/ghttp_request_method_query.go similarity index 97% rename from net/ghttp/ghttp_request_query.go rename to net/ghttp/ghttp_request_method_query.go index 4f81d2be6..bfb6e333c 100644 --- a/net/ghttp/ghttp_request_query.go +++ b/net/ghttp/ghttp_request_method_query.go @@ -17,7 +17,6 @@ import ( "github.com/gogf/gf/util/gconv" ) -// 初始化GET请求参数 func (r *Request) initGet() { if !r.parsedGet { r.parsedGet = true @@ -35,13 +34,11 @@ func (r *Request) initGet() { } } -// 设置当前请求的GET参数 func (r *Request) SetQuery(key string, value interface{}) { r.initGet() r.getMap[key] = value } -// 获得指定名称的get参数列表 func (r *Request) GetQuery(key string, def ...interface{}) interface{} { r.initGet() if v, ok := r.getMap[key]; ok { diff --git a/net/ghttp/ghttp_request_request.go b/net/ghttp/ghttp_request_request.go index 68fafc935..aeab4ba02 100644 --- a/net/ghttp/ghttp_request_request.go +++ b/net/ghttp/ghttp_request_request.go @@ -99,8 +99,6 @@ func (r *Request) GetRequestInterfaces(key string, def ...interface{}) []interfa return r.GetRequestVar(key, def...).Interfaces() } -// 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值 -// 需要注意的是,如果其中一个字段为数组形式,那么只会返回第一个元素,如果需要获取全部的元素,请使用GetRequestArray获取特定字段内容 func (r *Request) GetRequestMap(kvMap ...map[string]interface{}) map[string]interface{} { r.initRaw() m := r.rawVarMap @@ -150,7 +148,6 @@ func (r *Request) GetRequestMapStrVar(kvMap ...map[string]interface{}) map[strin return nil } -// 将所有的request参数映射到struct属性上,参数object应当为一个struct对象的指针, mapping为非必需参数,自定义参数与属性的映射关系 func (r *Request) GetRequestToStruct(pointer interface{}, mapping ...map[string]string) error { tagMap := structs.TagMapName(pointer, paramTagPriority, true) if len(mapping) > 0 { diff --git a/net/ghttp/ghttp_unit_param_test.go b/net/ghttp/ghttp_unit_param_test.go index 26bda8f10..66063bb0d 100644 --- a/net/ghttp/ghttp_unit_param_test.go +++ b/net/ghttp/ghttp_unit_param_test.go @@ -25,6 +25,7 @@ func Test_Params_Basic(t *testing.T) { } p := ports.PopRand() s := g.Server(p) + // GET s.BindHandler("/get", func(r *ghttp.Request) { if r.GetQuery("array") != nil { r.Response.Write(r.GetQuery("array")) @@ -57,38 +58,40 @@ func Test_Params_Basic(t *testing.T) { r.Response.Write(r.GetQueryMapStrStr()["a"]) } }) + // PUT s.BindHandler("/put", func(r *ghttp.Request) { - if r.Get("array") != nil { - r.Response.Write(r.Get("array")) + if r.GetPut("array") != nil { + r.Response.Write(r.GetPut("array")) } - if r.Get("slice") != nil { - r.Response.Write(r.Get("slice")) + if r.GetPut("slice") != nil { + r.Response.Write(r.GetPut("slice")) } - if r.Get("bool") != nil { - r.Response.Write(r.GetBool("bool")) + if r.GetPut("bool") != nil { + r.Response.Write(r.GetPutBool("bool")) } - if r.Get("float32") != nil { - r.Response.Write(r.GetFloat32("float32")) + if r.GetPut("float32") != nil { + r.Response.Write(r.GetPutFloat32("float32")) } - if r.Get("float64") != nil { - r.Response.Write(r.GetFloat64("float64")) + if r.GetPut("float64") != nil { + r.Response.Write(r.GetPutFloat64("float64")) } - if r.Get("int") != nil { - r.Response.Write(r.GetInt("int")) + if r.GetPut("int") != nil { + r.Response.Write(r.GetPutInt("int")) } - if r.Get("uint") != nil { - r.Response.Write(r.GetUint("uint")) + if r.GetPut("uint") != nil { + r.Response.Write(r.GetPutUint("uint")) } - if r.Get("string") != nil { - r.Response.Write(r.GetString("string")) + if r.GetPut("string") != nil { + r.Response.Write(r.GetPutString("string")) } - if r.Get("map") != nil { - r.Response.Write(r.GetMap()["map"].(map[string]interface{})["b"]) + if r.GetPut("map") != nil { + r.Response.Write(r.GetPutMap()["map"].(map[string]interface{})["b"]) } - if r.Get("a") != nil { - r.Response.Write(r.GetMapStrStr()["a"]) + if r.GetPut("a") != nil { + r.Response.Write(r.GetPutMapStrStr()["a"]) } }) + // POST s.BindHandler("/post", func(r *ghttp.Request) { if r.GetPost("array") != nil { r.Response.Write(r.GetPost("array")) @@ -121,6 +124,39 @@ func Test_Params_Basic(t *testing.T) { r.Response.Write(r.GetPostMapStrStr()["a"]) } }) + // DELETE + s.BindHandler("/delete", func(r *ghttp.Request) { + if r.GetDelete("array") != nil { + r.Response.Write(r.GetDelete("array")) + } + if r.GetDelete("slice") != nil { + r.Response.Write(r.GetDelete("slice")) + } + if r.GetDelete("bool") != nil { + r.Response.Write(r.GetDeleteBool("bool")) + } + if r.GetDelete("float32") != nil { + r.Response.Write(r.GetDeleteFloat32("float32")) + } + if r.GetDelete("float64") != nil { + r.Response.Write(r.GetDeleteFloat64("float64")) + } + if r.GetDelete("int") != nil { + r.Response.Write(r.GetDeleteInt("int")) + } + if r.GetDelete("uint") != nil { + r.Response.Write(r.GetDeleteUint("uint")) + } + if r.GetDelete("string") != nil { + r.Response.Write(r.GetDeleteString("string")) + } + if r.GetDelete("map") != nil { + r.Response.Write(r.GetDeleteMap()["map"].(map[string]interface{})["b"]) + } + if r.GetDelete("a") != nil { + r.Response.Write(r.GetDeleteMapStrStr()["a"]) + } + }) s.BindHandler("/map", func(r *ghttp.Request) { if m := r.GetQueryMap(); len(m) > 0 { r.Response.Write(m["name"]) @@ -231,6 +267,21 @@ func Test_Params_Basic(t *testing.T) { gtest.Assert(client.PostContent("/post", "map[a]=1&map[b]=2"), `2`) gtest.Assert(client.PostContent("/post", "a=1&b=2"), `1`) + // DELETE + gtest.Assert(client.DeleteContent("/delete", "array[]=1&array[]=2"), `["1","2"]`) + gtest.Assert(client.DeleteContent("/delete", "slice=1&slice=2"), `2`) + gtest.Assert(client.DeleteContent("/delete", "bool=1"), `true`) + gtest.Assert(client.DeleteContent("/delete", "bool=0"), `false`) + gtest.Assert(client.DeleteContent("/delete", "float32=0.11"), `0.11`) + gtest.Assert(client.DeleteContent("/delete", "float64=0.22"), `0.22`) + gtest.Assert(client.DeleteContent("/delete", "int=-10000"), `-10000`) + gtest.Assert(client.DeleteContent("/delete", "int=10000"), `10000`) + gtest.Assert(client.DeleteContent("/delete", "uint=10000"), `10000`) + gtest.Assert(client.DeleteContent("/delete", "uint=9"), `9`) + gtest.Assert(client.DeleteContent("/delete", "string=key"), `key`) + gtest.Assert(client.DeleteContent("/delete", "map[a]=1&map[b]=2"), `2`) + gtest.Assert(client.DeleteContent("/delete", "a=1&b=2"), `1`) + // Map gtest.Assert(client.GetContent("/map", "id=1&name=john"), `john`) gtest.Assert(client.PostContent("/map", "id=1&name=john"), `john`) diff --git a/os/gtime/gtime_format.go b/os/gtime/gtime_format.go index dbc3252fb..1d2b46e46 100644 --- a/os/gtime/gtime_format.go +++ b/os/gtime/gtime_format.go @@ -15,52 +15,39 @@ import ( ) var ( - // Please refer: http://php.net/manual/en/function.date.php + // Refer: http://php.net/manual/en/function.date.php formats = map[byte]string{ - // ================== Day ================== - 'd': "02", // Day of the month, 2 digits with leading zeros. Eg: 01 to 31 - 'D': "Mon", // A textual representation of a day, three letters. Eg: Mon through Sun - 'w': "Monday", // Numeric representation of the day of the week. Eg: 0 (for Sunday) through 6 (for Saturday) - 'N': "Monday", // ISO-8601 numeric representation of the day of the week. Eg: 1 (for Monday) through 7 (for Sunday) - 'j': "=j=02", // Day of the month without leading zeros. Eg: 1 to 31 - 'S': "02", // English ordinal suffix for the day of the month, 2 characters. Eg: st, nd, rd or th. Works well with j - 'l': "Monday", // A full textual representation of the day of the week. Eg: Sunday through Saturday - 'z': "", // The day of the year (starting from 0). Eg: 0 through 365 - - // ================== Week ================== - 'W': "", // ISO-8601 week number of year, weeks starting on Monday. Eg: 42 (the 42nd week in the year) - - // ================== Month ================== - 'F': "January", // A full textual representation of a month, such as January or March. Eg: January through December - 'm': "01", // Numeric representation of a month, with leading zeros. Eg: 01 through 12 - 'M': "Jan", // A short textual representation of a month, three letters. Eg: Jan through Dec - 'n': "1", // Numeric representation of a month, without leading zeros. Eg: 1 through 12 - 't': "", // Number of days in the given month. Eg: 28 through 31 - - // ================== Year ================== - 'Y': "2006", // A full numeric representation of a year, 4 digits. Eg: 1999 or 2003 - 'y': "06", // A two digit representation of a year. Eg: 99 or 03 - - // ================== Time ================== - 'a': "pm", // Lowercase Ante meridiem and Post meridiem. Eg: am or pm - 'A': "PM", // Uppercase Ante meridiem and Post meridiem. Eg: AM or PM - 'g': "3", // 12-hour format of an hour without leading zeros. Eg: 1 through 12 - 'G': "=G=15", // 24-hour format of an hour without leading zeros. Eg: 0 through 23 - 'h': "03", // 12-hour format of an hour with leading zeros. Eg: 01 through 12 - 'H': "15", // 24-hour format of an hour with leading zeros. Eg: 00 through 23 - 'i': "04", // Minutes with leading zeros. Eg: 00 to 59 - 's': "05", // Seconds with leading zeros. Eg: 00 through 59 - 'u': "=u=.000", // Milliseconds. Eg: 234, 678 - 'U': "", // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). - - // ================== Zone ================== - 'O': "-0700", // Difference to Greenwich time (GMT) in hours. Eg: +0200 - 'P': "-07:00", // Difference to Greenwich time (GMT) with colon between hours and minutes. Eg: +02:00 - 'T': "MST", // Timezone abbreviation. Eg: UTC, EST, MDT ... - - // ================== Format ================== - 'c': "2006-01-02T15:04:05-07:00", // ISO 8601 date. Eg: 2004-02-12T15:19:21+00:00 - 'r': "Mon, 02 Jan 06 15:04 MST", // RFC 2822 formatted date. Eg: Thu, 21 Dec 2000 16:01:07 +0200 + 'd': "02", // Day: Day of the month, 2 digits with leading zeros. Eg: 01 to 31. + 'D': "Mon", // Day: A textual representation of a day, three letters. Eg: Mon through Sun. + 'w': "Monday", // Day: Numeric representation of the day of the week. Eg: 0 (for Sunday) through 6 (for Saturday). + 'N': "Monday", // Day: ISO-8601 numeric representation of the day of the week. Eg: 1 (for Monday) through 7 (for Sunday). + 'j': "=j=02", // Day: Day of the month without leading zeros. Eg: 1 to 31. + 'S': "02", // Day: English ordinal suffix for the day of the month, 2 characters. Eg: st, nd, rd or th. Works well with j. + 'l': "Monday", // Day: A full textual representation of the day of the week. Eg: Sunday through Saturday. + 'z': "", // Day: The day of the year (starting from 0). Eg: 0 through 365. + 'W': "", // Week: ISO-8601 week number of year, weeks starting on Monday. Eg: 42 (the 42nd week in the year). + 'F': "January", // Month: A full textual representation of a month, such as January or March. Eg: January through December. + 'm': "01", // Month: Numeric representation of a month, with leading zeros. Eg: 01 through 12. + 'M': "Jan", // Month: A short textual representation of a month, three letters. Eg: Jan through Dec. + 'n': "1", // Month: Numeric representation of a month, without leading zeros. Eg: 1 through 12. + 't': "", // Month: Number of days in the given month. Eg: 28 through 31. + 'Y': "2006", // Year: A full numeric representation of a year, 4 digits. Eg: 1999 or 2003. + 'y': "06", // Year: A two digit representation of a year. Eg: 99 or 03. + 'a': "pm", // Time: Lowercase Ante meridiem and Post meridiem. Eg: am or pm. + 'A': "PM", // Time: Uppercase Ante meridiem and Post meridiem. Eg: AM or PM. + 'g': "3", // Time: 12-hour format of an hour without leading zeros. Eg: 1 through 12. + 'G': "=G=15", // Time: 24-hour format of an hour without leading zeros. Eg: 0 through 23. + 'h': "03", // Time: 12-hour format of an hour with leading zeros. Eg: 01 through 12. + 'H': "15", // Time: 24-hour format of an hour with leading zeros. Eg: 00 through 23. + 'i': "04", // Time: Minutes with leading zeros. Eg: 00 to 59. + 's': "05", // Time: Seconds with leading zeros. Eg: 00 through 59. + 'u': "=u=.000", // Time: Milliseconds. Eg: 234, 678. + 'U': "", // Time: Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). + 'O': "-0700", // Zone: Difference to Greenwich time (GMT) in hours. Eg: +0200. + 'P': "-07:00", // Zone: Difference to Greenwich time (GMT) with colon between hours and minutes. Eg: +02:00. + 'T': "MST", // Zone: Timezone abbreviation. Eg: UTC, EST, MDT ... + 'c': "2006-01-02T15:04:05-07:00", // Format: ISO 8601 date. Eg: 2004-02-12T15:19:21+00:00. + 'r': "Mon, 02 Jan 06 15:04 MST", // Format: RFC 2822 formatted date. Eg: Thu, 21 Dec 2000 16:01:07 +0200. } // Week to number mapping.