sebastiandev / zipper

C++ wrapper around minizip compression library
MIT License
515 stars 123 forks source link

Feature request: Automatic timestamp for files #74

Closed Togtja closed 3 years ago

Togtja commented 4 years ago

When zipping files on a system, make the timestamp of the file a part of the zipping.

Currently, unless you specify the timestamp yourself, Zipper gives an empty std::tm:

    zipper::Zipper zipf("test.zip");
    zipf.add("test.txt");
    zipf.close();

The file timestamp will look like this: image

Now currently, as stated you can give a timestamp yourself, so the workaround would be something like this:

    //Get the last write time in filesystem clock
    auto time = std::filesystem::last_write_time("test.txt");
    //A "dirty" way to convert filesystem clock to system_clock, and then get the time_point
    auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
        time - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now());
    //use the time_point to to get the time_t
    auto timet           = std::chrono::system_clock::to_time_t(sctp);
    //convert the time_t to std::tm
    const auto timestamp = *std::localtime(&timet);
    std::ifstream inp("test.txt");
    zipper::Zipper zip("test.zip");
    zip.add(inp, timestamp, "test.txt");
    zip.close();

One issue is that converting std::chrono::file_clock to std::chrono::system_clock to then use system_clock's to_time_t, now there should be UNIX and Windows call to more accurately get a file's timestamp. C++20 seeks to fix this issue. Another is the very minor inaccuracy as I call ::now() twice to convert to the time. see SO for more details.

Anyways the result in this: image It is decades more accurate than what is currently here, and cross-platform. However to be very proper (before C++20), then a timestamp on unix would look something like this:

    #include <sys/stat.h>
    struct stat buf;
    stat("test.txt", &buf);
    zipper::Zipper zip("test.zip");
    auto timet           = static_cast<time_t>(buf.st_mtim.tv_sec);
    const auto timestamp = *std::localtime(&timet);
    zip.add(inp, timestamp, "test.txt");
    zip.close();

On Windows, you probably need to call GetFileTime from the API. I am not a windows machine for the moment, so can't draft anything.

It would be really nice if the timestamp got set automatically when calling the bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags)constructor, as there you have to open the file/folder and can also do this read. `

Lecrapouille commented 3 years ago

Afaik when doing this:

std::ifstream inp("test.txt");
zip.add(inp, "test.txt"); 

inp has lost its filename so it'll be difficult to get its timestamp.

Togtja commented 3 years ago

That is true, but when you call zip.add("test.txt"); you can grap the file date. In the case of zip.add(inp, "test.txt")I beleve the default time date should be now() i.e the date/time you currently are in right now

Lecrapouille commented 3 years ago

We can add helper Class methods:

Togtja commented 3 years ago

as #97 is merged, I will close this