Skip to content

Commit 4adcf4d

Browse files
Default enable DefaultUTCTimeZone (#1130)
1 parent af0bf8e commit 4adcf4d

File tree

6 files changed

+404
-269
lines changed

6 files changed

+404
-269
lines changed

cel/cel_test.go

Lines changed: 144 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,55 +2146,157 @@ func TestRegexOptimizer(t *testing.T) {
21462146
}
21472147
}
21482148

2149-
func TestDefaultUTCTimeZone(t *testing.T) {
2150-
env := testEnv(t, Variable("x", TimestampType), DefaultUTCTimeZone(true))
2151-
out, err := interpret(t, env, `
2152-
x.getFullYear() == 1970
2153-
&& x.getMonth() == 0
2154-
&& x.getDayOfYear() == 0
2155-
&& x.getDayOfMonth() == 0
2156-
&& x.getDate() == 1
2157-
&& x.getDayOfWeek() == 4
2158-
&& x.getHours() == 2
2159-
&& x.getMinutes() == 5
2160-
&& x.getSeconds() == 6
2161-
&& x.getMilliseconds() == 1
2162-
&& x.getFullYear('-07:30') == 1969
2163-
&& x.getDayOfYear('-07:30') == 364
2164-
&& x.getMonth('-07:30') == 11
2165-
&& x.getDayOfMonth('-07:30') == 30
2166-
&& x.getDate('-07:30') == 31
2167-
&& x.getDayOfWeek('-07:30') == 3
2168-
&& x.getHours('-07:30') == 18
2169-
&& x.getMinutes('-07:30') == 35
2170-
&& x.getSeconds('-07:30') == 6
2171-
&& x.getMilliseconds('-07:30') == 1
2172-
&& x.getFullYear('23:15') == 1970
2173-
&& x.getDayOfYear('23:15') == 1
2174-
&& x.getMonth('23:15') == 0
2175-
&& x.getDayOfMonth('23:15') == 1
2176-
&& x.getDate('23:15') == 2
2177-
&& x.getDayOfWeek('23:15') == 5
2178-
&& x.getHours('23:15') == 1
2179-
&& x.getMinutes('23:15') == 20
2180-
&& x.getSeconds('23:15') == 6
2181-
&& x.getMilliseconds('23:15') == 1`,
2182-
map[string]any{
2183-
"x": time.Unix(7506, 1000000).Local(),
2184-
})
2185-
if err != nil {
2186-
t.Fatalf("prg.Eval() failed: %v", err)
2149+
func TestDefaultUTCTimeZoneDisabled(t *testing.T) {
2150+
testEnvs := []struct {
2151+
name string
2152+
env *Env
2153+
}{
2154+
{"default", testEnv(t, Variable("x", TimestampType))},
2155+
{"enabled", testEnv(t, Variable("x", TimestampType), DefaultUTCTimeZone(true))},
2156+
{"disabled", testEnv(t, Variable("x", TimestampType), DefaultUTCTimeZone(false))},
2157+
}
2158+
exprs := []struct {
2159+
name string
2160+
value string
2161+
envOut map[string]ref.Val
2162+
}{
2163+
{
2164+
name: "default-timezone",
2165+
value: `
2166+
x.getFullYear() == 1970
2167+
&& x.getMonth() == 0
2168+
&& x.getDayOfYear() == 0
2169+
&& x.getDayOfMonth() == 0
2170+
&& x.getDate() == 1
2171+
&& x.getDayOfWeek() == 4
2172+
&& x.getHours() == 2
2173+
&& x.getMinutes() == 5
2174+
&& x.getSeconds() == 6
2175+
&& x.getMilliseconds() == 1`,
2176+
envOut: map[string]ref.Val{
2177+
"default": types.True,
2178+
"enabled": types.True,
2179+
"disabled": types.False,
2180+
},
2181+
},
2182+
{
2183+
name: "default-local-year",
2184+
value: `x.getFullYear()`,
2185+
envOut: map[string]ref.Val{
2186+
"default": types.Int(1970),
2187+
"enabled": types.Int(1970),
2188+
"disabled": types.Int(1969),
2189+
},
2190+
},
2191+
{
2192+
name: "default-local-day-of-year",
2193+
value: `x.getDayOfYear()`,
2194+
envOut: map[string]ref.Val{
2195+
"default": types.Int(0),
2196+
"enabled": types.Int(0),
2197+
"disabled": types.Int(364),
2198+
},
2199+
},
2200+
{
2201+
name: "default-local-month",
2202+
value: `x.getMonth()`,
2203+
envOut: map[string]ref.Val{
2204+
"default": types.Int(0),
2205+
"enabled": types.Int(0),
2206+
"disabled": types.Int(11),
2207+
},
2208+
},
2209+
{
2210+
name: "default-local-day-of-month",
2211+
value: `
2212+
x.getDayOfMonth() == 30
2213+
&& x.getDate() == 31`,
2214+
envOut: map[string]ref.Val{
2215+
"default": types.False,
2216+
"enabled": types.False,
2217+
"disabled": types.True,
2218+
},
2219+
},
2220+
{
2221+
name: "default-local-dates",
2222+
value: `x.getDayOfWeek()`,
2223+
envOut: map[string]ref.Val{
2224+
"default": types.Int(4),
2225+
"enabled": types.Int(4),
2226+
"disabled": types.Int(3),
2227+
},
2228+
},
2229+
{
2230+
name: "default-local-times",
2231+
value: `
2232+
x.getHours() == 18
2233+
&& x.getMinutes() == 5
2234+
&& x.getSeconds() == 6
2235+
&& x.getMilliseconds() == 1`,
2236+
envOut: map[string]ref.Val{
2237+
"default": types.False,
2238+
"enabled": types.False,
2239+
"disabled": types.True,
2240+
},
2241+
},
2242+
{
2243+
name: "explicit",
2244+
value: `
2245+
x.getFullYear('-07:30') == 1969
2246+
&& x.getDayOfYear('-07:30') == 364
2247+
&& x.getMonth('-07:30') == 11
2248+
&& x.getDayOfMonth('-07:30') == 30
2249+
&& x.getDate('-07:30') == 31
2250+
&& x.getDayOfWeek('-07:30') == 3
2251+
&& x.getHours('-07:30') == 18
2252+
&& x.getMinutes('-07:30') == 35
2253+
&& x.getSeconds('-07:30') == 6
2254+
&& x.getMilliseconds('-07:30') == 1
2255+
&& x.getFullYear('23:15') == 1970
2256+
&& x.getDayOfYear('23:15') == 1
2257+
&& x.getMonth('23:15') == 0
2258+
&& x.getDayOfMonth('23:15') == 1
2259+
&& x.getDate('23:15') == 2
2260+
&& x.getDayOfWeek('23:15') == 5
2261+
&& x.getHours('23:15') == 1
2262+
&& x.getMinutes('23:15') == 20
2263+
&& x.getSeconds('23:15') == 6
2264+
&& x.getMilliseconds('23:15') == 1`,
2265+
envOut: map[string]ref.Val{
2266+
"default": types.True,
2267+
"enabled": types.True,
2268+
"disabled": types.True,
2269+
},
2270+
},
21872271
}
2188-
if out != types.True {
2189-
t.Errorf("Eval() got %v, wanted true", out)
2272+
2273+
offset, _ := time.ParseDuration("-8h")
2274+
vars := map[string]any{
2275+
"x": time.Unix(7506, 1000000).In(time.FixedZone("", int(offset.Seconds()))),
2276+
}
2277+
for _, e := range testEnvs {
2278+
te := e
2279+
for _, expr := range exprs {
2280+
ex := expr
2281+
t.Run(fmt.Sprintf("%s/%s", te.name, ex.name), func(t *testing.T) {
2282+
env := te.env
2283+
expr := ex.value
2284+
out, err := interpret(t, env, expr, vars)
2285+
if err != nil {
2286+
t.Fatal(err)
2287+
}
2288+
if out.Equal(ex.envOut[te.name]) != types.True {
2289+
t.Errorf("interpret got %v, wanted %v", out, ex.envOut[te.name])
2290+
}
2291+
})
2292+
}
21902293
}
21912294
}
21922295

21932296
func TestDefaultUTCTimeZoneExtension(t *testing.T) {
21942297
env := testEnv(t,
21952298
Variable("x", TimestampType),
21962299
Variable("y", DurationType),
2197-
DefaultUTCTimeZone(true),
21982300
)
21992301
env, err := env.Extend()
22002302
if err != nil {
@@ -2220,7 +2322,7 @@ func TestDefaultUTCTimeZoneExtension(t *testing.T) {
22202322
}
22212323

22222324
func TestDefaultUTCTimeZoneError(t *testing.T) {
2223-
env := testEnv(t, Variable("x", TimestampType), DefaultUTCTimeZone(true))
2325+
env := testEnv(t, Variable("x", TimestampType))
22242326
out, err := interpret(t, env, `
22252327
x.getFullYear(':xx') == 1969
22262328
|| x.getDayOfYear('xx:') == 364

cel/env.go

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -718,10 +718,15 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) {
718718
}
719719
}
720720

721-
// If the default UTC timezone fix has been enabled, make sure the library is configured
722-
e, err = e.maybeApplyFeature(featureDefaultUTCTimeZone, Lib(timeUTCLibrary{}))
723-
if err != nil {
724-
return nil, err
721+
// If the default UTC timezone has been disabled, configure the legacy overloads
722+
if utcTime, isSet := e.features[featureDefaultUTCTimeZone]; isSet && !utcTime {
723+
if !e.appliedFeatures[featureDefaultUTCTimeZone] {
724+
e.appliedFeatures[featureDefaultUTCTimeZone] = true
725+
e, err = Lib(timeLegacyLibrary{})(e)
726+
if err != nil {
727+
return nil, err
728+
}
729+
}
725730
}
726731

727732
// Configure the parser.
@@ -805,27 +810,6 @@ func (e *Env) getCheckerOrError() (*checker.Env, error) {
805810
return e.chk, e.chkErr
806811
}
807812

808-
// maybeApplyFeature determines whether the feature-guarded option is enabled, and if so applies
809-
// the feature if it has not already been enabled.
810-
func (e *Env) maybeApplyFeature(feature int, option EnvOption) (*Env, error) {
811-
if !e.HasFeature(feature) {
812-
return e, nil
813-
}
814-
_, applied := e.appliedFeatures[feature]
815-
if applied {
816-
return e, nil
817-
}
818-
e, err := option(e)
819-
if err != nil {
820-
return nil, err
821-
}
822-
// record that the feature has been applied since it will generate declarations
823-
// and functions which will be propagated on Extend() calls and which should only
824-
// be registered once.
825-
e.appliedFeatures[feature] = true
826-
return e, nil
827-
}
828-
829813
// computeUnknownVars determines a set of missing variables based on the input activation and the
830814
// environment's configured declaration set.
831815
func (e *Env) computeUnknownVars(vars Activation) []*interpreter.AttributePattern {

0 commit comments

Comments
 (0)