From b85c2aef095e89ac100463810b0035f72888d4e0 Mon Sep 17 00:00:00 2001 From: 26huitailang <26huitailang@gmail.com> Date: Mon, 18 Nov 2024 15:19:58 +0800 Subject: [PATCH] fix: ModTime support time.Location --- .gitignore | 4 ++++ crypto_test.go | 2 +- demo/localtime/main.go | 34 ++++++++++++++++++++++++++++++++++ go.mod | 8 ++++++++ struct.go | 16 ++++++++++------ zip_test.go | 16 +++++++++++++--- 6 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 demo/localtime/main.go create mode 100644 go.mod diff --git a/.gitignore b/.gitignore index 72747d6..0213061 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,7 @@ _testmain.go *.exe *.test *.prof + +vendor/ +.idea/ +/go.sum diff --git a/crypto_test.go b/crypto_test.go index e7b7277..257013c 100644 --- a/crypto_test.go +++ b/crypto_test.go @@ -56,7 +56,7 @@ func TestPasswordHelloWorldAes(t *testing.T) { var b bytes.Buffer for _, f := range r.File { if !f.IsEncrypted() { - t.Errorf("Expected %s to be encrypted.", f.FileInfo().Name) + t.Errorf("Expected %s to be encrypted.", f.FileInfo().Name()) } f.SetPassword("golang") rc, err := f.Open() diff --git a/demo/localtime/main.go b/demo/localtime/main.go new file mode 100644 index 0000000..8658341 --- /dev/null +++ b/demo/localtime/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "bytes" + "github.com/26huitailang/zip" + "io" + "log" + "os" + "time" +) + +func main() { + contents := []byte("Hello World") + fzip, err := os.Create(`./test.zip`) + if err != nil { + log.Fatalln(err) + } + fh := &zip.FileHeader{ + Name: `test.txt`, + Method: zip.Deflate, + } + fh.SetModTime(time.Now(), time.Local) + zipw := zip.NewWriter(fzip) + w, err := zipw.CreateHeader(fh) + if err != nil { + log.Fatal(err) + } + defer zipw.Close() + _, err = io.Copy(w, bytes.NewReader(contents)) + if err != nil { + log.Fatal(err) + } + zipw.Flush() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a8e2b98 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/26huitailang/zip + +go 1.23.2 + +require ( + github.com/alexmullins/zip v0.0.0-20180717182244-4affb64b04d0 + golang.org/x/crypto v0.29.0 +) diff --git a/struct.go b/struct.go index 1e0cba2..0f4f953 100644 --- a/struct.go +++ b/struct.go @@ -133,13 +133,13 @@ func (fi headerFileInfo) Sys() interface{} { return fi.fh } // Because os.FileInfo's Name method returns only the base name of // the file it describes, it may be necessary to modify the Name field // of the returned header to provide the full path name of the file. -func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) { +func FileInfoHeader(fi os.FileInfo, loc *time.Location) (*FileHeader, error) { size := fi.Size() fh := &FileHeader{ Name: fi.Name(), UncompressedSize64: uint64(size), } - fh.SetModTime(fi.ModTime()) + fh.SetModTime(fi.ModTime(), loc) fh.SetMode(fi.Mode()) if fh.UncompressedSize64 > uint32max { fh.UncompressedSize = uint32max @@ -183,8 +183,12 @@ func msDosTimeToTime(dosDate, dosTime uint16) time.Time { // timeToMsDosTime converts a time.Time to an MS-DOS date and time. // The resolution is 2s. // See: http://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx -func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) { - t = t.In(time.UTC) +func timeToMsDosTime(t time.Time, loc *time.Location) (fDate uint16, fTime uint16) { + if loc == nil { + t = t.In(time.UTC) + } else { + t = t.In(loc) + } fDate = uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9) fTime = uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11) return @@ -198,8 +202,8 @@ func (h *FileHeader) ModTime() time.Time { // SetModTime sets the ModifiedTime and ModifiedDate fields to the given time in UTC. // The resolution is 2s. -func (h *FileHeader) SetModTime(t time.Time) { - h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t) +func (h *FileHeader) SetModTime(t time.Time, loc *time.Location) { + h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t, loc) } const ( diff --git a/zip_test.go b/zip_test.go index f00ff47..73f5733 100644 --- a/zip_test.go +++ b/zip_test.go @@ -53,7 +53,17 @@ func TestOver65kFiles(t *testing.T) { func TestModTime(t *testing.T) { var testTime = time.Date(2009, time.November, 10, 23, 45, 58, 0, time.UTC) fh := new(FileHeader) - fh.SetModTime(testTime) + fh.SetModTime(testTime, nil) + outTime := fh.ModTime() + if !outTime.Equal(testTime) { + t.Errorf("times don't match: got %s, want %s", outTime, testTime) + } +} + +func TestModTimeLocal(t *testing.T) { + var testTime = time.Date(2009, time.November, 10, 23, 45, 58, 0, time.Local) + fh := new(FileHeader) + fh.SetModTime(testTime, nil) outTime := fh.ModTime() if !outTime.Equal(testTime) { t.Errorf("times don't match: got %s, want %s", outTime, testTime) @@ -62,7 +72,7 @@ func TestModTime(t *testing.T) { func testHeaderRoundTrip(fh *FileHeader, wantUncompressedSize uint32, wantUncompressedSize64 uint64, t *testing.T) { fi := fh.FileInfo() - fh2, err := FileInfoHeader(fi) + fh2, err := FileInfoHeader(fi, nil) if err != nil { t.Fatal(err) } @@ -390,7 +400,7 @@ func TestHeaderInvalidTagAndSize(t *testing.T) { Method: Deflate, Extra: []byte(ts.Format(time.RFC3339Nano)), // missing tag and len } - h.SetModTime(ts) + h.SetModTime(ts, nil) testInvalidHeader(&h, t) }