@@ -2,14 +2,15 @@ package plugin
22
33import (
44 "fmt"
5+ "github.com/grafana/grafana-plugin-sdk-go/backend"
56 "regexp"
67 "strconv"
78 "strings"
89 "time"
910)
1011
11- // 判断不区分大小写的键是否存在于 map[string] 中,并获取对应的值
12- func getValueIgnoreCase (data map [string ]interface {}, keys []string ) (interface {}, bool ) {
12+ // GetValueIgnoreCase 判断不区分大小写的键是否存在于 map[string] 中,并获取对应的值
13+ func GetValueIgnoreCase (data map [string ]interface {}, keys []string ) (interface {}, bool ) {
1314 for _ , key := range keys {
1415 for k , v := range data {
1516 if strings .EqualFold (k , key ) {
@@ -20,30 +21,79 @@ func getValueIgnoreCase(data map[string]interface{}, keys []string) (interface{}
2021 return "" , false
2122}
2223
23- // 时间正则匹配
24- // formatDateTime 根据给定的格式字符串(如 "${__from:date:iso}"、"${__from:date:iso+n}"、"${__from:date:iso-n}" 或 "${__from:date}")和时间戳,
25- // 解析时区信息(如果存在)并应用到日期时间的格式化输出。
26- func formatDateTime (formatStr string , timestamp time.Time ) (string , error ) {
27- switch formatStr {
28- case "${__from}" :
29- t := timestamp .String ()
30- return t , nil
31- case "${__from:date:seconds}" :
32- t := timestamp .Unix ()
33- return strconv .FormatInt (t , 10 ), nil
34- case "${__from:date:iso}" :
35- // 默认使用 UTC 时间
36- t := timestamp .UTC ()
37- return t .Format (time .RFC3339 ), nil
24+ var datePatternRegex = regexp .MustCompile ("(LT|LL?L?L?|l{1,4}|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|Q)" )
25+
26+ var datePatternReplacements = map [string ]string {
27+ "M" : "1" , // stdNumMonth 1 2 ... 11 12
28+ "MM" : "01" , // stdZeroMonth 01 02 ... 11 12
29+ "MMM" : "Jan" , // stdMonth Jan Feb ... Nov Dec
30+ "MMMM" : "January" , // stdLongMonth January February ... November December
31+ "D" : "2" , // stdDay 1 2 ... 30 30
32+ "DD" : "02" , // stdZeroDay 01 02 ... 30 31
33+ "DDD" : "<stdDayOfYear>" , // Day of the year 1 2 ... 364 365
34+ "DDDD" : "<stdDayOfYearZero>" , // Day of the year 001 002 ... 364 365 @todo****
35+ "d" : "<stdDayOfWeek>" , // Numeric representation of day of the week 0 1 ... 5 6
36+ "dd" : "Mon" , // ***Su Mo ... Fr Sa @todo
37+ "ddd" : "Mon" , // Sun Mon ... Fri Sat
38+ "dddd" : "Monday" , // stdLongWeekDay Sunday Monday ... Friday Saturday
39+ "e" : "<stdDayOfWeek>" , // Numeric representation of day of the week 0 1 ... 5 6 @todo
40+ "E" : "<stdDayOfWeekISO>" , // ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0) 1 2 ... 6 7 @todo
41+ "w" : "<stdWeekOfYear>" , // 1 2 ... 52 53
42+ "ww" : "<stdWeekOfYear>" , // ***01 02 ... 52 53 @todo
43+ "W" : "<stdWeekOfYear>" , // 1 2 ... 52 53
44+ "WW" : "<stdWeekOfYear>" , // ***01 02 ... 52 53 @todo
45+ "YY" : "06" , // stdYear 70 71 ... 29 30
46+ "YYYY" : "2006" , // stdLongYear 1970 1971 ... 2029 2030
47+ "gg" : "<stdIsoYearShort>" , // ISO-8601 year number 70 71 ... 29 30
48+ "gggg" : "<stdIsoYear>" , // ***1970 1971 ... 2029 2030
49+ "GG" : "<stdIsoYearShort>" , // 70 71 ... 29 30
50+ "GGGG" : "<stdIsoYear>" , // ***1970 1971 ... 2029 2030
51+ "Q" : "<stdQuarter>" , // 1, 2, 3, 4
52+ "A" : "PM" , // stdPM AM PM
53+ "a" : "pm" , // stdpm am pm
54+ "H" : "<stdHourNoZero>" , // stdHour 0 1 ... 22 23
55+ "HH" : "15" , // 00 01 ... 22 23
56+ "h" : "3" , // stdHour12 1 2 ... 11 12
57+ "hh" : "03" , // stdZeroHour12 01 02 ... 11 12
58+ "m" : "4" , // stdZeroMinute 0 1 ... 58 59
59+ "mm" : "04" , // stdZeroMinute 00 01 ... 58 59
60+ "s" : "5" , // stdSecond 0 1 ... 58 59
61+ "ss" : "05" , // stdZeroSecond ***00 01 ... 58 59
62+ "z" : "MST" , // EST CST ... MST PST
63+ "zz" : "MST" , // EST CST ... MST PST
64+ "Z" : "Z07:00" , // stdNumColonTZ -07:00 -06:00 ... +06:00 +07:00
65+ "ZZ" : "-0700" , // stdNumTZ -0700 -0600 ... +0600 +0700
66+ "X" : "<stdUnix>" , // Seconds since unix epoch 1360013296
67+ "LT" : "3:04 PM" , // 8:30 PM
68+ "L" : "01/02/2006" , // 09/04/1986
69+ "l" : "1/2/2006" , // 9/4/1986
70+ "ll" : "Jan 2 2006" , // Sep 4 1986
71+ "lll" : "Jan 2 2006 3:04 PM" , // Sep 4 1986 8:30 PM
72+ "llll" : "Mon, Jan 2 2006 3:04 PM" , // Thu, Sep 4 1986 8:30 PM
73+ }
74+
75+ func patternToLayout (pattern string ) string {
76+ var match [][]string
77+ if match = datePatternRegex .FindAllStringSubmatch (pattern , - 1 ); match == nil {
78+ return pattern
79+ }
3880
39- case "${__from:date}" :
40- // 使用本地时间
41- t := timestamp .Local ()
42- return t .Format ("2006-01-02 15:04:05" ), nil
81+ for i := range match {
82+ if replace , ok := datePatternReplacements [match [i ][0 ]]; ok {
83+ pattern = strings .Replace (pattern , match [i ][0 ], replace , 1 )
84+ }
85+ }
86+
87+ return pattern
88+ }
4389
44- default :
45- // 检查是否存在时区偏移量
46- re := regexp .MustCompile (`\$\{__from:date:iso([+-])(-?\d+)\}` )
90+ // FormatDateTime 时间正则匹配: 根据给定的格式字符串和时间戳,
91+ // 解析时区信息(如果存在)并应用到日期时间的格式化输出。
92+ func FormatDateTime (formatStr string , timestamp time.Time ) (string , error ) {
93+ hasTimeOffset := strings .Contains (strings .ToLower (formatStr ), "utc" )
94+ loc := time .FixedZone ("" , 0 )
95+ if hasTimeOffset {
96+ re := regexp .MustCompile (`.*?utc([+-])(\d+).*?` )
4797 matches := re .FindStringSubmatch (formatStr )
4898 fmt .Println ("matches:" , matches )
4999 if len (matches ) == 3 {
@@ -64,34 +114,29 @@ func formatDateTime(formatStr string, timestamp time.Time) (string, error) {
64114 }
65115
66116 // 创建对应时区
67- loc := time .FixedZone ("" , int (offsetDuration .Seconds ()))
68-
69- // 使用给定的时间戳和时区进行格式化
70- t := timestamp .In (loc )
71- return t .Format ("2006-01-02 15:04:05" ), nil
117+ loc = time .FixedZone ("" , int (offsetDuration .Seconds ()))
72118 }
119+ }
73120
74- return "" , fmt .Errorf ("unsupported format string: %s" , formatStr )
121+ pattern := time .RFC3339
122+ re := regexp .MustCompile (`"(.+?)"` )
123+ matches := re .FindStringSubmatch (formatStr )
124+ if len (matches ) > 1 {
125+ format := matches [1 ]
126+ pattern = patternToLayout (format )
75127 }
128+
129+ return timestamp .In (loc ).Format (pattern ), nil
76130}
77131
78- // formatDateTimeForQuery 根据给定的格式字符串、查询时间范围对象(queryTimeRange)和时间类型(fromOrTo),
132+ // FormatDateTimeForQuery 根据给定的格式字符串、查询时间范围对象(queryTimeRange)和时间类型(fromOrTo),
79133// 格式化相应的时间(起始时间或结束时间)。
80- func formatDateTimeForQuery (formatStr string , queryTimeRange QueryTimeRange , fromOrTo string ) (string , error ) {
134+ func FormatDateTimeForQuery (formatStr string , queryTimeRange backend. TimeRange ) (string , error ) {
81135 timestamp := queryTimeRange .From
82- if fromOrTo == "to" {
136+ // 如果formatStr包含"__to",则使用结束时间,否则使用起始时间
137+ // 并全部替换为__from
138+ if strings .Contains (formatStr , "__time_to" ) {
83139 timestamp = queryTimeRange .To
84140 }
85-
86- // 替换格式字符串中的 "__from" 为 "__to"
87- if fromOrTo == "to" {
88- formatStr = strings .ReplaceAll (formatStr , "${__from}" , "${__to}" )
89- }
90-
91- return formatDateTime (formatStr , timestamp )
92- }
93-
94- type QueryTimeRange struct {
95- From time.Time
96- To time.Time
141+ return FormatDateTime (formatStr , timestamp )
97142}
0 commit comments