(ESP32 + time.h + SD card) How to add leading a "0" to month and date and time?

I am using the ESP32 with Time.h library to log data on the SD card.
I am successfully logging data with date and time.
but help me in adding a leading "0" if the month, date, hour, min or sec is a single digit number.
Below is the part of the code I am using to log the data to the SD card.

  void logSDCard() {
    dataMessage = String(timeinfo.tm_year+1900) + "-" + String(timeinfo.tm_mon+1) + "-" + String(timeinfo.tm_mday) + "," + String(timeinfo.tm_hour) + ":" + String(timeinfo.tm_min) + ":" + String(timeinfo.tm_sec) + "\r\n"; 
    Serial.print("Save data: ");
    Serial.println(dataMessage);
    appendFile(SD, path.c_str(), dataMessage.c_str());
  }

Don't use String, use sprintf_P

1 Like

I struck the same issue putting the time from a RTC on an OLED on my motorbike.

I read a number of solutions - most just seemed overly complicated. The one I settled for in the end was simple and straight-forward.

Here's the entire routine - hope it helps.

void updateOLED()                                                                 // Write current time to OLED display
{
  DateTime now = rtc.now();                                                       // Get the current time from the RTC

  display.clearDisplay();                                                         // Clear the display so we don't get artifacts
  display.setCursor(0,0);                                                         // Start at top-left corner
  
  if (now.hour() < 10)                                                            // Leading "0" required before hour?
  {
    display.println("0");                                                         // If so then write it to the OLED buffer and ...
    display.setCursor(32,0);                                                      // Move the cursor for the next digit
  }
  
  display.println(now.hour(), DEC);                                               // Write the current hour to the OLED buffer
  
  display.setCursor(66,0);                                                        // Setup for correct minutes position

  if (now.minute() < 10)                                                          // Leading "0" required before minute?
  {
    display.println("0");                                                         // If so then write it to the OLED buffer
    display.setCursor(98,0);                                                      // and move the cursor for the next digit
  }
  
  display.println(now.minute(), DEC);                                             // Write the current minute to the buffer
  
  display.display();                                                              // Display the buffer contents on the OLED
}

With ESP32, there is a method printf in the Print class, so you can do for example :

Serial.printf( "%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min ); 

Are you using ESP32 too ? If yes, display should have a printf method too, so you can do like in my previous reply

No - mine is just running on a Pro mini. Reason I posted is that most of the solutions I Googled seemed to focus on trying to beat the output into shape using libraries with significant footprints and overheads whereas it seemed to be easily handled just by simply testing that data.

Thought that would port over to any program pretty easily. Sounds like your solution is even easier though.

if it was just printing then I would have used your code, but how can I replace this line below which I am using to write to the SD card..?

    dataMessage = String(timeinfo.tm_year+1900) + "-" + String(timeinfo.tm_mon+1) + "-" + String(timeinfo.tm_mday) + "," + String(timeinfo.tm_hour) + ":" + String(timeinfo.tm_min) + ":" + String(timeinfo.tm_sec) + "\r\n"; 

By using sprintf, and not using a String at all?

1 Like

Is this fine..?

sprintf_P(buff, PSTR("%02d"), timeinfo.tm_mon+1)

Does the ESP32 have sprintf_P?

What happened when you tried it?

1 Like

No error in compilation and upload. But does not give any output.
I have also tried

 sprintf(buff, PSTR("%02d"), timeinfo.tm_mon+1)

Still not working

Hint: don't ever use that phrase here

Hint 2: post your code.

1 Like

:roll_eyes: Sorry for that..

Currently what my code does at this stage is, it pulls the time from server and then logging the date & time every second. Later it will log lot of other parameters along, every second on a new file everyday. The file name will by the date of the file.
Also the date and time which I am logging, I want the month, date. hour, mins and seconds with a leading 0.

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

int t=0;
int m = 0;
struct tm timeinfo;
char buff[10];

const char* ssid     = "SSID";
const char* password = "pass";

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 19800;
const int   daylightOffset_sec = 0;

String dataMessage;
String date;
String path;
String filename;

void getdate(){
  date= String(timeinfo.tm_min);
}

void getpath() {
  path = "/" + filename;
  Serial.print("Path: ");
  Serial.println(path);
}

void getFileName() {
  File close();
  filename = date + ".txt";
  Serial.print("File name: ");
  Serial.println(filename);

}

//=========================== WRITE FUNCTION ============================//
// Write to the SD card (DON'T MODIFY THIS FUNCTION)
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();
}

//=========================== APPEND FUNCTION ============================//

// Append data to the SD card (DON'T MODIFY THIS FUNCTION)
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();
}

//============================= LOGGING FUNCTION ================================//
  void logSDCard() {
//    dataMessage = String(timeinfo.tm_year+1900) + "-" + String(timeinfo.tm_mon+1) + "-" + String(timeinfo.tm_mday) + "," + String(timeinfo.tm_hour) + ":" + String(timeinfo.tm_min) + ":" + String(timeinfo.tm_sec) + "\r\n"; 
    dataMessage = sprintf(buff, PSTR("%02d"), timeinfo.tm_mon+1);
    Serial.print("Save data: ");
    Serial.println(dataMessage);
    appendFile(SD, path.c_str(), dataMessage.c_str());
  }


//================================ SETUP ================================//
void setup() {
  pinMode(5, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, INPUT_PULLUP);
  pinMode(23, INPUT_PULLUP);

  
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("Contacting Time Server");  


  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  

  Serial.print("Initializing SD card...");

      // Initialize SD card
        SD.begin(5);  
        if(!SD.begin(5)) {
          Serial.println("Card Mount Failed");
          return;
        }
        uint8_t cardType = SD.cardType();
        if(cardType == CARD_NONE) {
          Serial.println("No SD card attached");
          return;
        }
        Serial.println("Initializing SD card...");
        if (!SD.begin(5)) {
          Serial.println("ERROR - SD card initialization failed!");
          return;    // init failed
        }


} //End of SETUP



//================================ LOOP ================================//
void loop() {
  
  
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }

  if(m != timeinfo.tm_min){
    getdate();
    Serial.println(date);
    getFileName();
    getpath();
//    writeFile(SD, path.c_str(), "Parameter \r\n");
  
    m=timeinfo.tm_min;
  }

  

  if(t != timeinfo.tm_sec){

  logSDCard();
    
    t=timeinfo.tm_sec;
  }

} // End of LOOP

sprintf returns the number of characters printed. You should be printing "buff"

1 Like

Ahh...
Thank you so much .. How could I miss that silly thing..
You have always helped me out AWOL..
Have learnt a lot form you.

sprintf(buff, PSTR("%02d"), timeinfo.tm_mon+1);
dataMessage = (buff);

Just lose the String!

I believe the sprintf will require much more less space than the String. Am I right..?

I didn't understand that, but you're passing a string to appendFile anyway, so why bother converting to a String?

Ohh.. correct..
Its just that I will not have to write multiple lines.

Also I came to know about the PSTR that it saves the strings to the flash memory..
how does that help and what if I do not use the PSTR in the sprintf..?

If you don't want to use PSTR, lose it, and drop the "_P"

1 Like