touch: parse documented timestamp formats

This commit is contained in:
Nicholas Velten
2026-09-09 10:24:48 +01:00
committed by Nick Craig-Wood
parent ea589de941
commit e45210765c
3 changed files with 54 additions and 11 deletions
+23 -9
View File
@@ -26,10 +26,19 @@ var (
const (
defaultLayout string = "060102"
layoutDate string = "2006-01-02"
layoutDateWithTime string = "2006-01-02T15:04:05"
layoutDateWithTimeNano string = "2006-01-02T15:04:05.999999999"
)
var timeLayouts = []string{
time.RFC3339Nano,
layoutDateWithTimeNano,
layoutDateWithTime,
layoutDate,
defaultLayout,
}
func init() {
cmd.Root.AddCommand(commandDefinition)
cmdFlags := commandDefinition.Flags()
@@ -56,9 +65,11 @@ This will touch ` + "`--transfers`" + ` files concurrently.
If ` + "`--timestamp`" + ` is used then sets the modification time to that
time instead of the current time. Times may be specified as one of:
- 'YYMMDD' - e.g. 17.10.30
- 'YYMMDD' - e.g. 171030
- 'YYYY-MM-DD' - e.g. 2006-01-02
- 'YYYY-MM-DDTHH:MM:SS' - e.g. 2006-01-02T15:04:05
- 'YYYY-MM-DDTHH:MM:SS.SSS' - e.g. 2006-01-02T15:04:05.123456789
- 'YYYY-MM-DDTHH:MM:SSZ' - e.g. 2006-01-02T15:04:05Z
Note that value of ` + "`--timestamp`" + ` is in UTC. If you want local time
then add the ` + "`--localtime`" + ` flag.
@@ -100,16 +111,19 @@ func newFsDst(args []string) (f fs.Fs, remote string) {
// parseTimeArgument parses a timestamp string according to specific layouts
func parseTimeArgument(timeString string) (time.Time, error) {
layout := defaultLayout
if len(timeString) == len(layoutDateWithTime) {
layout = layoutDateWithTime
} else if len(timeString) > len(layoutDateWithTime) {
layout = layoutDateWithTimeNano
}
var err error
for _, layout := range timeLayouts {
var t time.Time
if localTime {
return time.ParseInLocation(layout, timeString, time.Local)
t, err = time.ParseInLocation(layout, timeString, time.Local)
} else {
t, err = time.Parse(layout, timeString)
}
return time.Parse(layout, timeString)
if err == nil {
return t, nil
}
}
return time.Time{}, err
}
// timeOfTouch returns the time value set on files
+27
View File
@@ -3,6 +3,7 @@ package touch
import (
"context"
"testing"
"time"
_ "github.com/rclone/rclone/backend/local"
"github.com/rclone/rclone/fs"
@@ -21,6 +22,32 @@ func checkFile(t *testing.T, r fs.Fs, path string, content string) {
fstest.CheckItems(t, r, file1)
}
func TestParseTimeArgument(t *testing.T) {
oldLocalTime := localTime
localTime = false
t.Cleanup(func() {
localTime = oldLocalTime
})
for _, test := range []struct {
in string
want time.Time
}{
{"171030", fstest.Time("2017-10-30T00:00:00Z")},
{"2024-05-01", fstest.Time("2024-05-01T00:00:00Z")},
{"2024-05-01T12:00:00", fstest.Time("2024-05-01T12:00:00Z")},
{"2024-05-01T12:00:00.123456789", fstest.Time("2024-05-01T12:00:00.123456789Z")},
{"2024-05-01T12:00:00Z", fstest.Time("2024-05-01T12:00:00Z")},
{"2024-05-01T12:00:00.123456789Z", fstest.Time("2024-05-01T12:00:00.123456789Z")},
} {
t.Run(test.in, func(t *testing.T) {
got, err := parseTimeArgument(test.in)
require.NoError(t, err)
require.Equal(t, test.want, got)
})
}
}
// TestMain drives the tests
func TestMain(m *testing.M) {
fstest.TestMain(m)
+3 -1
View File
@@ -24,9 +24,11 @@ This will touch `--transfers` files concurrently.
If `--timestamp` is used then sets the modification time to that
time instead of the current time. Times may be specified as one of:
- 'YYMMDD' - e.g. 17.10.30
- 'YYMMDD' - e.g. 171030
- 'YYYY-MM-DD' - e.g. 2006-01-02
- 'YYYY-MM-DDTHH:MM:SS' - e.g. 2006-01-02T15:04:05
- 'YYYY-MM-DDTHH:MM:SS.SSS' - e.g. 2006-01-02T15:04:05.123456789
- 'YYYY-MM-DDTHH:MM:SSZ' - e.g. 2006-01-02T15:04:05Z
Note that value of `--timestamp` is in UTC. If you want local time
then add the `--localtime` flag.