Update time parser to handle OneDrive format (#1013)

## Description

OneDrive format uses '-' in place of ':'. Purge command needs to be able to clear folders with this format as well.

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [ ] 🌻 Feature
- [x] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🐹 Trivial/Minor

## Issue(s)

* closes #1012

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-09-30 15:38:43 -07:00 committed by GitHub
parent dd7b84871f
commit b612718723
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 39 deletions

View File

@ -9,9 +9,10 @@ import (
const ( const (
// the clipped format occurs when m365 removes the :00 second suffix // the clipped format occurs when m365 removes the :00 second suffix
ClippedSimpleTimeFormat = "02-Jan-2006_15:04" ClippedSimpleTimeFormat = "02-Jan-2006_15:04"
LegacyTimeFormat = time.RFC3339 ClippedSimpleTimeFormatOneDrive = "02-Jan-2006_15-04"
SimpleDateTimeFormat = "02-Jan-2006_15:04:05" LegacyTimeFormat = time.RFC3339
SimpleDateTimeFormat = "02-Jan-2006_15:04:05"
// SimpleDateTimeFormatOneDrive is similar to `SimpleDateTimeFormat` // SimpleDateTimeFormatOneDrive is similar to `SimpleDateTimeFormat`
// but uses `-` instead of `:` which is a reserved character in // but uses `-` instead of `:` which is a reserved character in
// OneDrive // OneDrive
@ -21,11 +22,13 @@ const (
) )
var ( var (
clippedSimpleTimeRE = regexp.MustCompile(`.*(\d{2}-[a-zA-Z]{3}-\d{4}_\d{2}:\d{2}).*`) clippedSimpleTimeRE = regexp.MustCompile(`.*(\d{2}-[a-zA-Z]{3}-\d{4}_\d{2}:\d{2}).*`)
legacyTimeRE = regexp.MustCompile( clippedSimpleTimeOneDriveRE = regexp.MustCompile(`.*(\d{2}-[a-zA-Z]{3}-\d{4}_\d{2}-\d{2}).*`)
legacyTimeRE = regexp.MustCompile(
`.*(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}?([Zz]|[a-zA-Z]{2}|([\+|\-]([01]\d|2[0-3])))).*`) `.*(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}?([Zz]|[a-zA-Z]{2}|([\+|\-]([01]\d|2[0-3])))).*`)
simpleDateTimeRE = regexp.MustCompile(`.*(\d{2}-[a-zA-Z]{3}-\d{4}_\d{2}:\d{2}:\d{2}).*`) simpleDateTimeRE = regexp.MustCompile(`.*(\d{2}-[a-zA-Z]{3}-\d{4}_\d{2}:\d{2}:\d{2}).*`)
standardTimeRE = regexp.MustCompile( simpleDateTimeOneDriveRE = regexp.MustCompile(`.*(\d{2}-[a-zA-Z]{3}-\d{4}_\d{2}-\d{2}-\d{2}).*`)
standardTimeRE = regexp.MustCompile(
`.*(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?([Zz]|[a-zA-Z]{2}|([\+|\-]([01]\d|2[0-3])))).*`) `.*(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?([Zz]|[a-zA-Z]{2}|([\+|\-]([01]\d|2[0-3])))).*`)
tabularOutputTimeRE = regexp.MustCompile(`.*(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}([Zz]|[a-zA-Z]{2})).*`) tabularOutputTimeRE = regexp.MustCompile(`.*(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}([Zz]|[a-zA-Z]{2})).*`)
) )
@ -33,10 +36,22 @@ var (
var ( var (
// clipped formats must appear last, else they take priority over the regular Simple format. // clipped formats must appear last, else they take priority over the regular Simple format.
formats = []string{ formats = []string{
StandardTimeFormat, SimpleDateTimeFormat, LegacyTimeFormat, TabularOutputTimeFormat, ClippedSimpleTimeFormat, StandardTimeFormat,
SimpleDateTimeFormat,
SimpleDateTimeFormatOneDrive,
LegacyTimeFormat,
TabularOutputTimeFormat,
ClippedSimpleTimeFormat,
ClippedSimpleTimeFormatOneDrive,
} }
regexes = []*regexp.Regexp{ regexes = []*regexp.Regexp{
standardTimeRE, simpleDateTimeRE, legacyTimeRE, tabularOutputTimeRE, clippedSimpleTimeRE, standardTimeRE,
simpleDateTimeRE,
simpleDateTimeOneDriveRE,
legacyTimeRE,
tabularOutputTimeRE,
clippedSimpleTimeRE,
clippedSimpleTimeOneDriveRE,
} }
) )
@ -48,29 +63,34 @@ func FormatNow(fmt string) string {
return time.Now().UTC().Format(fmt) return time.Now().UTC().Format(fmt)
} }
// FormatTimeWith produces the a datetime with the given format.
func FormatTimeWith(t time.Time, fmt string) string {
return t.UTC().Format(fmt)
}
// FormatTime produces the standard format for corso time values. // FormatTime produces the standard format for corso time values.
// Always formats into the UTC timezone. // Always formats into the UTC timezone.
func FormatTime(t time.Time) string { func FormatTime(t time.Time) string {
return t.UTC().Format(StandardTimeFormat) return FormatTimeWith(t, StandardTimeFormat)
} }
// FormatSimpleDateTime produces a simple datetime of the format // FormatSimpleDateTime produces a simple datetime of the format
// "02-Jan-2006_15:04:05" // "02-Jan-2006_15:04:05"
func FormatSimpleDateTime(t time.Time) string { func FormatSimpleDateTime(t time.Time) string {
return t.UTC().Format(SimpleDateTimeFormat) return FormatTimeWith(t, SimpleDateTimeFormat)
} }
// FormatTabularDisplayTime produces the standard format for displaying // FormatTabularDisplayTime produces the standard format for displaying
// a timestamp as part of user-readable cli output. // a timestamp as part of user-readable cli output.
// "2016-01-02T15:04:05Z" // "2016-01-02T15:04:05Z"
func FormatTabularDisplayTime(t time.Time) string { func FormatTabularDisplayTime(t time.Time) string {
return t.UTC().Format(TabularOutputTimeFormat) return FormatTimeWith(t, TabularOutputTimeFormat)
} }
// FormatLegacyTime produces standard format for string values // FormatLegacyTime produces standard format for string values
// that are placed in SingleValueExtendedProperty tags // that are placed in SingleValueExtendedProperty tags
func FormatLegacyTime(t time.Time) string { func FormatLegacyTime(t time.Time) string {
return t.UTC().Format(LegacyTimeFormat) return FormatTimeWith(t, LegacyTimeFormat)
} }
// ParseTime makes a best attempt to produce a time value from // ParseTime makes a best attempt to produce a time value from

View File

@ -57,15 +57,11 @@ func (suite *CommonTimeUnitSuite) TestParseTime() {
} }
func (suite *CommonTimeUnitSuite) TestExtractTime() { func (suite *CommonTimeUnitSuite) TestExtractTime() {
clipSimpleTime := func(t string) string { comparable := func(t *testing.T, tt time.Time, clippedFormat string) time.Time {
return t[:len(t)-3]
}
comparable := func(t *testing.T, tt time.Time, clipped bool) time.Time {
ts := common.FormatLegacyTime(tt.UTC()) ts := common.FormatLegacyTime(tt.UTC())
if clipped { if len(clippedFormat) > 0 {
ts = tt.UTC().Format(common.ClippedSimpleTimeFormat) ts = tt.UTC().Format(clippedFormat)
} }
c, err := common.ParseTime(ts) c, err := common.ParseTime(ts)
@ -95,16 +91,15 @@ func (suite *CommonTimeUnitSuite) TestExtractTime() {
type timeFormatter func(time.Time) string type timeFormatter func(time.Time) string
var ( formats := []string{
clippedF = func(t time.Time) string { common.ClippedSimpleTimeFormat,
return clipSimpleTime(common.FormatSimpleDateTime(t)) common.ClippedSimpleTimeFormatOneDrive,
} common.LegacyTimeFormat,
legacyF = common.FormatLegacyTime common.SimpleDateTimeFormat,
simpleF = common.FormatSimpleDateTime common.SimpleDateTimeFormatOneDrive,
stdF = common.FormatTime common.StandardTimeFormat,
tabularF = common.FormatTabularDisplayTime common.TabularOutputTimeFormat,
formatters = []timeFormatter{legacyF, simpleF, stdF, tabularF, clippedF} }
)
type presuf struct { type presuf struct {
prefix string prefix string
@ -119,23 +114,29 @@ func (suite *CommonTimeUnitSuite) TestExtractTime() {
} }
type testable struct { type testable struct {
input string input string
expect time.Time clippedFormat string
clipped bool expect time.Time
} }
table := []testable{} table := []testable{}
// test matrix: for each input, in each format, with each prefix/suffix, run the test. // test matrix: for each input, in each format, with each prefix/suffix, run the test.
for _, in := range inputs { for _, in := range inputs {
for i, f := range formatters { for _, f := range formats {
v := f(in) clippedFormat := f
if f != common.ClippedSimpleTimeFormat && f != common.ClippedSimpleTimeFormatOneDrive {
clippedFormat = ""
}
v := common.FormatTimeWith(in, f)
for _, ps := range pss { for _, ps := range pss {
table = append(table, testable{ table = append(table, testable{
input: ps.prefix + v + ps.suffix, input: ps.prefix + v + ps.suffix,
expect: comparable(suite.T(), in, i == 4), expect: comparable(suite.T(), in, clippedFormat),
clipped: i == 4, clippedFormat: clippedFormat,
}) })
} }
} }
@ -145,7 +146,7 @@ func (suite *CommonTimeUnitSuite) TestExtractTime() {
suite.T().Run(test.input, func(t *testing.T) { suite.T().Run(test.input, func(t *testing.T) {
result, err := common.ExtractTime(test.input) result, err := common.ExtractTime(test.input)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, test.expect, comparable(t, result, test.clipped)) assert.Equal(t, test.expect, comparable(t, result, test.clippedFormat))
}) })
} }
} }