-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
ctimefmt.go
143 lines (131 loc) · 4.36 KB
/
ctimefmt.go
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
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Keep the original license.
// Copyright 2019 Dmitry A. Mottl. All rights reserved.
// Use of this source code is governed by MIT license
// that can be found in the LICENSE file.
package ctimefmt // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/timeutils/internal/ctimefmt"
import (
"errors"
"fmt"
"regexp"
"time"
)
var ctimeRegexp = regexp.MustCompile(`%.`)
var decimalsRegexp = regexp.MustCompile(`\d`)
var ctimeSubstitutes = map[string]string{
"%Y": "2006",
"%y": "06",
"%m": "01",
"%o": "_1",
"%q": "1",
"%b": "Jan",
"%h": "Jan",
"%B": "January",
"%d": "02",
"%e": "_2",
"%g": "2",
"%a": "Mon",
"%A": "Monday",
"%H": "15",
"%l": "3",
"%I": "03",
"%p": "PM",
"%P": "pm",
"%M": "04",
"%S": "05",
"%L": "999",
"%f": "999999",
"%s": "99999999",
"%Z": "MST",
"%z": "Z0700",
"%w": "-070000",
"%i": "-07",
"%j": "-07:00",
"%k": "-07:00:00",
"%D": "01/02/2006",
"%x": "01/02/2006",
"%F": "2006-01-02",
"%T": "15:04:05",
"%X": "15:04:05",
"%r": "03:04:05 pm",
"%R": "15:04",
"%n": "\n",
"%t": "\t",
"%%": "%",
"%c": "Mon Jan 02 15:04:05 2006",
}
// Format returns a textual representation of the time value formatted
// according to ctime-like format string. Possible directives are:
//
// %Y - Year, zero-padded (0001, 0002, ..., 2019, 2020, ..., 9999)
// %y - Year, last two digits, zero-padded (01, ..., 99)
// %m - Month as a decimal number (01, 02, ..., 12)
// %o - Month as a space-padded number ( 1, 2, ..., 12)
// %q - Month as a unpadded number (1,2,...,12)
// %b, %h - Abbreviated month name (Jan, Feb, ...)
// %B - Full month name (January, February, ...)
// %d - Day of the month, zero-padded (01, 02, ..., 31)
// %e - Day of the month, space-padded ( 1, 2, ..., 31)
// %g - Day of the month, unpadded (1,2,...,31)
// %a - Abbreviated weekday name (Sun, Mon, ...)
// %A - Full weekday name (Sunday, Monday, ...)
// %H - Hour (24-hour clock) as a zero-padded decimal number (00, ..., 24)
// %I - Hour (12-hour clock) as a zero-padded decimal number (00, ..., 12)
// %l - Hour (12-hour clock: 0, ..., 12)
// %p - Locale’s equivalent of either AM or PM
// %P - Locale’s equivalent of either am or pm
// %M - Minute, zero-padded (00, 01, ..., 59)
// %S - Second as a zero-padded decimal number (00, 01, ..., 59)
// %L - Millisecond as a decimal number, zero-padded on the left (000, 001, ..., 999)
// %f - Microsecond as a decimal number, zero-padded on the left (000000, ..., 999999)
// %s - Nanosecond as a decimal number, zero-padded on the left (000000, ..., 999999)
// %z - UTC offset in the form ±HHMM[SS[.ffffff]] or empty(+0000, -0400)
// %Z - Timezone name or abbreviation or empty (UTC, EST, CST)
// %D, %x - Short MM/DD/YY date, equivalent to %m/%d/%y
// %F - Short YYYY-MM-DD date, equivalent to %Y-%m-%d
// %T, %X - ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
// %r - 12-hour clock time (02:55:02 pm)
// %R - 24-hour HH:MM time, equivalent to %H:%M
// %n - New-line character ('\n')
// %t - Horizontal-tab character ('\t')
// %% - A % sign
// %c - Date and time representation (Mon Jan 02 15:04:05 2006)
func Format(format string, t time.Time) (string, error) {
native, err := ToNative(format)
if err != nil {
return "", err
}
return t.Format(native), nil
}
// Parse parses a ctime-like formatted string (e.g. "%Y-%m-%d ...") and returns
// the time value it represents.
//
// Refer to Format() function documentation for possible directives.
func Parse(format, value string) (time.Time, error) {
native, err := ToNative(format)
if err != nil {
return time.Time{}, nil
}
return time.Parse(native, value)
}
// ToNative converts ctime-like format string to Go native layout
// (which is used by time.Time.Format() and time.Parse() functions).
func ToNative(format string) (string, error) {
if match := decimalsRegexp.FindString(format); match != "" {
return "", errors.New("format string should not contain decimals")
}
var errs []error
replaceFunc := func(directive string) string {
if subst, ok := ctimeSubstitutes[directive]; ok {
return subst
}
errs = append(errs, errors.New("unsupported ctimefmt.ToNative() directive: "+directive))
return ""
}
replaced := ctimeRegexp.ReplaceAllStringFunc(format, replaceFunc)
if len(errs) != 0 {
return "", fmt.Errorf("convert to go time format: %v", errs)
}
return replaced, nil
}