github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/utils/time.go (about) 1 // Copyright 2021 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package utils 15 16 import ( 17 "strings" 18 "time" 19 20 "github.com/pingcap/tidb/pkg/types" 21 "github.com/pingcap/tidb/pkg/util/dbutil" 22 "github.com/pingcap/tiflow/dm/pkg/terror" 23 ) 24 25 const ( 26 StartTimeFormat = "2006-01-02 15:04:05" 27 StartTimeFormat2 = "2006-01-02T15:04:05" 28 ) 29 30 // ParseTimeZone parse the time zone location by name or offset 31 // 32 // NOTE: we don't support the "SYSTEM" or "Local" time_zone. 33 func ParseTimeZone(s string) (*time.Location, error) { 34 if s == "SYSTEM" || s == "Local" { 35 return nil, terror.ErrConfigInvalidTimezone.New("'SYSTEM' or 'Local' time_zone is not supported") 36 } 37 38 loc, err := time.LoadLocation(s) 39 if err == nil { 40 return loc, nil 41 } 42 43 // The value can be given as a string indicating an offset from UTC, such as '+10:00' or '-6:00'. 44 // The time zone's value should in [-12:59,+14:00]. 45 // See: https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html#time-zone-variables 46 if strings.HasPrefix(s, "+") || strings.HasPrefix(s, "-") { 47 d, _, err := types.ParseDuration(types.DefaultStmtNoWarningContext, s[1:], 0) 48 if err == nil { 49 if s[0] == '-' { 50 if d.Duration > 12*time.Hour+59*time.Minute { 51 return nil, terror.ErrConfigInvalidTimezone.Generate(s) 52 } 53 } else { 54 if d.Duration > 14*time.Hour { 55 return nil, terror.ErrConfigInvalidTimezone.Generate(s) 56 } 57 } 58 59 ofst := int(d.Duration / time.Second) 60 if s[0] == '-' { 61 ofst = -ofst 62 } 63 name := dbutil.FormatTimeZoneOffset(d.Duration) 64 return time.FixedZone(name, ofst), nil 65 } 66 } 67 68 return nil, terror.ErrConfigInvalidTimezone.Generate(s) 69 } 70 71 // ParseStartTime parses start-time of task-start and validation-start in local location. 72 func ParseStartTime(timeStr string) (time.Time, error) { 73 return ParseStartTimeInLoc(timeStr, time.Local) 74 } 75 76 // ParseStartTimeInLoc parses start-time of task-start and validation-start. 77 func ParseStartTimeInLoc(timeStr string, loc *time.Location) (time.Time, error) { 78 t, err := time.ParseInLocation(StartTimeFormat, timeStr, loc) 79 if err != nil { 80 return time.ParseInLocation(StartTimeFormat2, timeStr, loc) 81 } 82 return t, nil 83 }