arduino-esp32 icon indicating copy to clipboard operation
arduino-esp32 copied to clipboard

Unnecessary timezone offset on file timestamp when working with SD.h

Open bot1131357 opened this issue 1 year ago • 6 comments

Board

ESP32 DevKit V1

Device Description

n/a

Hardware Configuration

ESP32 VSPI is connected to a microSD module: GPIO05 - SS GPIO23 - MOSI GPIO19 - MISO GPIO18 - SCLK

Version

v2.0.11

IDE Name

Platform IO

Operating System

Windows 11

Flash frequency

80 MHz

PSRAM enabled

no

Upload speed

115200

Description

When writing onto my SD card, the file timestamp seems to be affected by my timezone settings.

For testing, I have set the time to a constant value 1704067200 which corresponds to 2024-01-01 00:00:00 GMT.

Using const char* tz_posix = "CST-8"; I get the following:

Timezone: CST-8

Now is : 2024-01-01 08:00:00
Writing file: /hello.txt
File written
Appending to file: /hello.txt
Message appended
Listing directory: /
  FILE: hello.txt  SIZE: 13  LAST WRITE: 2024-01-01 08:00:00

08:00:00 is correct since CST-8 is 8 hours ahead of GMT, but when I read the SD card from my laptop the timestamp is actually 08:00:00 GMT instead of CST-8.

This is consistent when I tested with other timezones as well. The only one which seems unaffected is when I use const char* tz_posix = "GMT";

Is this a known issue, or am I going about this problem the wrong way?

Sketch

#include <Arduino.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <time.h> 

void writeFile(fs::FS &fs, const char * path, const char * message);
void appendFile(fs::FS &fs, const char * path, const char * message);
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);

//  const char* tz_posix = "EST+10EDT+11,M10.1.0/02:00:00,M4.1.0/03:00:00"; 
//  const char* tz_posix = "CST+8"; // test
// const char* tz_posix = "CST-8"; // test
//  const char* tz_posix = "MSK-3"; // test
//  const char* tz_posix = "BST-6"; // test
 const char* tz_posix = "JST-9"; // test
//  const char* tz_posix = "GMT"; 

void setup(){
    Serial.begin(115200);

    timeval tv{1704067200,0}; // test date Monday, January 1, 2024 12:00:00 AM GMT
    timezone tz;
    settimeofday(&tv,NULL);

    setenv("TZ", tz_posix, 1); 
    tzset();

    Serial.printf("Timezone: %s\r\n", tz_posix);

    struct tm tmstruct ;
    getLocalTime(&tmstruct, 5000);
    Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1900,( tmstruct.tm_mon)+1, tmstruct.tm_mday,tmstruct.tm_hour , tmstruct.tm_min, tmstruct.tm_sec);
    
    if(!SD.begin()){
        Serial.println("Card Mount Failed");
        return;
    }

    writeFile(SD, "/hello.txt", "Hello ");
    appendFile(SD, "/hello.txt", "World!\n");
    listDir(SD, "/", 0);
}

void loop(){}

// ==================================
// Utility functions

void writeFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("File written");
    } else {
        Serial.println("Write failed");
    }
    file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file){
        Serial.println("Failed to open file for appending");
        return;
    }
    if(file.print(message)){
        Serial.println("Message appended");
    } else {
        Serial.println("Append failed");
    }
    file.close();
}

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            // ignore
        } 
        else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.print(file.size());
            time_t t= file.getLastWrite();
            struct tm * utmstruct = gmtime(&t);
            struct tm * tmstruct = localtime(&t);
            Serial.printf("  LAST WRITE: %d-%02d-%02d %02d:%02d:%02d",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
        }
        file = root.openNextFile();
    }
}

Debug Message

// another test log
Timezone: JST-9

Now is : 2024-01-01 09:00:00
Writing file: /hello.txt
File written
Appending to file: /hello.txt
Message appended
Listing directory: /
  FILE: hello.txt  SIZE: 13  LAST WRITE: 2024-01-01 09:00:00

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • [X] I confirm I have checked existing issues, online documentation and Troubleshooting guide.

bot1131357 avatar Jan 07 '24 07:01 bot1131357

Just to clarify about the behavior: When you run this on the esp32, it all seems to work just fine, but if you take that SD card and put it in another machine, it seems like the times are wrong.
If you have WSL, can you open a terminal and run TZ="UTC" ls -l in the SD directory? Does it show the time as 0:00 or 8:00?

lbernstone avatar Jan 08 '24 22:01 lbernstone

Thanks for responding. I have verified on both my Windows and Linux machines.

No issues when timezone is set to GMT:

-rwxrwxrwx 1 user test 13 Jan  1 00:00 hello_gmt.txt
-rwxrwxrwx 1 user test 13 Jan  1 09:00 hello_jst.txt

I wonder if anyone else has encountered the same behaviour...

bot1131357 avatar Jan 09 '24 11:01 bot1131357

Hi @lbernstone, is this something you can reproduce on your end?

bot1131357 avatar Jan 19 '24 09:01 bot1131357

I am on vacation, so I don't have a sd card handy

lbernstone avatar Jan 20 '24 00:01 lbernstone

Thanks for replying. Have a good vacation!

bot1131357 avatar Jan 20 '24 12:01 bot1131357

Is there something I can test in the mean time?

bot1131357 avatar Feb 14 '24 02:02 bot1131357