Compiler error: no match for 'operator=' (operand types are 'tm' and 'tm*')

Hi, I am using - TimeLib.h //Time by Michael Margolis now maintained by Paul Stoffregen - NTPClient.. // NTP Client by Fabrice Weinberg - time.h /from Espressif

an am trying to populate the structure struct tm timeinfo with the c++ method:

time_t     Epoch;
struct tm  timeinfo;

...

void getTimeData()
{
timeinfo  = localtime ( &Epoch);
}

but currently my code breaks there with:

\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3/tools/sdk/libc/xtensa-lx106-elf/include/../include/time.h:31:8: note: no known conversion for argument 1 from 'tm*' to 'tm&&'

exit status 1 no match for 'operator=' (operand types are 'tm' and 'tm*')

I cannot figure out why.

Can someone help to do it the right way?

If you need details and the full code, the whole story and code is here:

P.S. the same error when I try to compile for ESP32: \AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4/tools/sdk/include/newlib/time.h:31:8: note: no known conversion for argument 1 from 'tm*' to 'tm&&'

exit status 1 no match for 'operator=' (operand types are 'tm' and 'tm*')

If I try to compile for an Uno it becomes weirder:

\Arduino\libraries\Time-master/time.h:1:2: warning: #warning "Please include TimeLib.h, not Time.h. Future versions will remove Time.h" [-Wcpp]

warning "Please include TimeLib.h, not Time.h. Future versions will remove Time.h"

^~~~~~~

37:12: error: aggregate 'tm timeinfo' has incomplete type and cannot be defined

struct tm timeinfo;

99:15: error: 'localtime' was not declared in this scope

timeinfo = localtime(&Epoch); // does not work...

^~~~~~~~~

exit status 1 aggregate 'tm timeinfo' has incomplete type and cannot be defined

Please post a complete program that illustrates the problem

Not much time but

struct tm  timeinfo;

should be

tmElements_t  timeinfo;

PS please post a complete example

UKHeliBob: Please post a complete program that illustrates the problem

Hm...I already referred to that at the end of my OP: :D "If you need details and the full code, the whole story and code is here: https://forum.arduino.cc/index.php?topic=682655.msg4592248"

"If you need details and the full code, the whole story and code is here: https://forum.arduino.cc/index.php?topic=682655.msg4592248"

If the whole story is there them why have you started a new thread ?

If this is a separate problem then you need to post your code here, not a link to it, so that the question can be seen in context

I still can't find localtime; it looks like that is ESP specific in ESP's time.h (and I don't have that).

I suspect that your problem is the mixing of Paul Stoffregen's TimeLib.h and Espressif's Time.h.

Note: In my previous answer I assumed TimeLib.h as includes were not specified in the snippet and hence the suggested modification.

UKHeliBob: If the whole story is there them why have you started a new thread ?

The first attempt was probably too long and too detailed: nobody answered and probably nobody did read it to the end.

That is always the same dilemma:

Explain everything from the beginning and reveal the whole complexity and nobody will read it.

Put only the core instructions around the problem, people will compain that you haven't posted everything. :(

At least I got an answer! :grinning:

sterretje:
I still can’t find localtime; it looks like that is ESP specific in ESP’s time.h (and I don’t have that).

I suspect that your problem is the mixing of Paul Stoffregen’s TimeLib.h and Espressif’s Time.h.

Note:
In my previous answer I assumed TimeLib.h as includes were not specified in the snippet and hence the suggested modification.

In fact I started with <NTPClient.h> // NTP Client by Fabrice Weinberg, the main library supplied by the IDE.

It should run on an Espressif device since almost every WiFi system in the Arduino world use it directly or indirectly on a shield.

But NTP Client ony provides a very basic time framework and has not provision for date functionalities.
The maintainers recommend to add TimeLib to get the full scope.

My project should run on Espressif devices since almost every WiFi system in the Arduino world use them directly or indirectly on a shield anyway.

The problem that I try to solve is that all these different libraries are incompatible and not fully Posix-compliant.

I want to write something really portable and that works with ctime as specified in c++, but also provides the data as simple variables, as strings and as char arrays.

//struct tm  timeinfo;
tm* timeinfo; //localtime returns a pointer to a tm struct

//sprintf(charbuff, "Now is %02d hour, %02d minutes and %02d seconds. The Epoch is: %10d" , r , Minute, Second, Epoch);
sprintf(charbuff, "Now is %02d hour, %02d minutes and %02d seconds. The Epoch is: %10lu" , Hour , Minute, Second, Epoch); //Epoch is an unsigned long int, not an int

//sprintf(charbuff, "Today is %03s, %02d %03s %04d ", DayName , Day , MonthName, Year);
sprintf(charbuff, "Today is %3s, %02d %3s %04d ", DayName , Day , MonthName, Year); //character strings are not padded with 0's, spaces will be used for padding if needed

Avoid defining time variables using common names such as Hour, Minute, Second, etc, because those tend to be used in the time libraries. Mixing two time libraries can lead to a lot of confusion also.

Apparently you can use the original code that you have:

struct tm* timeinfo;

But you are not using the correct method for extracting the data from the structure:

  timeinfo = localtime(&Epoch);
  Second    = timeinfo->tm_sec;
  Minute    = timeinfo->tm_min;
  Hour      = timeinfo->tm_hour;
  Weekday   = timeinfo->tm_wday; //day range 0 - 6, starting with Sunday
  Day       = timeinfo->tm_mday;
  Month     = timeinfo->tm_mon + 1; //month range 0 - 11
  Year      = timeinfo->tm_year + 1900; //returns years since 1900
  //note - you need to modify your char arrays because tm_wday and tm_mon begin at 0 not 1
  DayName   = daysOfTheWeek[timeinfo->tm_wday]; 
  MonthName = monthsOfTheYear[timeinfo->tm_mon];

It gets a bit confusing when you use two libraries that use similar names and functions, hard to guess at which library you want to use for a particular task.

david_2018:
Apparently you can use the original code that you have

But you are not using the correct method for extracting the data from the structure:

It gets a bit confusing when you use two libraries that use similar names and functions, hard to guess at which library you want to use for a particular task.

THANK YOU!
You are an angel!

Now I got it flying for ESP 32 and ESP8266 altogether.

It intentionally uses the variables and conventions of P. Stoffregen’s TimeLib library, so sketches that use it, will work the same way.

Additionally my example povides several methods to use time and dates.
Of course the Posix-one is the preferred…

//**Do not*** #include <TimeLib.h>, but mimic it!  
// Time by Michael Margolis now maintained by Paul Stoffregen

#include <NTPClient.h>    // NTP Client by Fabrice Weinberg
#if defined(ESP8266)
#include <ESP8266WiFi.h>  // default from Espressif
#include <WiFiUdp.h>      // default from Espressif  
#elif defined(ESP32)
#include <WiFi.h>         // default from Espressif
#endif

#define WIFI_SSID "GW-FM-7390"
#define WIFI_PASS "3tr67333"
#define HOST_NAME "ESP-IoT"
#define TZ            2               // (utc+) TZ in hours
#define DST_MN        60              // use 60mn for summer time in some countries
#define GMT_OFFSET_SEC 3600 * TZ      // Do not change here...
#define DAIYLIGHT_OFFSET_SEC 60 * DST_MN // Do not change here...
#define NTP_SERVER "de.pool.ntp.org"
char daysOfTheWeek[8][4] = {"???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; // Function begins with 1
char monthsOfTheYear[13][4] = {"???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; // Function begins with 1

// Variables for Time
static int lastSecond;
tm*        timeinfo;                 //localtime returns a pointer to a tm structstatic int Second;
time_t     Epoch;

static int Second;
static int Minute;
static int Hour;
static int Day;
static int Month;
static int Year;
static int Weekday;
char *     DayName;
char *     MonthName;
String     Time;
String     Today;

static IPAddress ip;

//*** Buffers ***
static char charbuff[80];    //Char buffer for many functions
//String text;                 //String buffer for many functions


// Constructors
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_SERVER, GMT_OFFSET_SEC);

void getWiFi()
{
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while ( WiFi.status() != WL_CONNECTED )
  {
    delay ( 500 );
    Serial.print ( "." );
  }
  ip = WiFi.localIP();
  sprintf(charbuff, "Connected to IP: %03d.%03d.%03d.%03d", ip[0], ip[1], ip[2], ip[3]);
  Serial.println(charbuff);
}

void getNTP()
{
  timeClient.begin();
  timeClient.update();
  Serial.print(timeClient.getFormattedTime());
}
void getEpoch()
{
  Epoch   = timeClient.getEpochTime();
}
void getTimeData()
{
  timeinfo  = localtime(&Epoch);  // cf: https://www.cplusplus.com/reference/ctime/localtime/
  Second    = timeinfo->tm_sec;
  Minute    = timeinfo->tm_min;
  Hour      = timeinfo->tm_hour;
  Weekday   = timeinfo->tm_wday +1 ; 
  Day       = timeinfo->tm_mday;
  Month     = timeinfo->tm_mon + 1; 
  Year      = timeinfo->tm_year + 1900; //returns years since 1900
  DayName   = daysOfTheWeek[Weekday];
  MonthName = monthsOfTheYear[Month];
  Time      = timeClient.getFormattedTime();
  sprintf(charbuff, "%02d/%02d/%04d", Day , Month, Year);
  Today     = charbuff;
}

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

}
void loop()
{
  timeClient.update();   // should be called from time to time to refresh NTP when expired, does nothing most of the time.
  getEpoch();            // writes the Epoch (Numbers of seconds till 1.1.1970...
  getTimeData();         // breaks down the Epoch into discrete values.

  // Examples with Strings
  Serial.print(F("Thanks God, it is: "));
  Serial.print( DayName );
  Serial.print(F("! Today is "));
  Serial.print( Today );
  Serial.print(F(" and Time is "));
  Serial.println( Time );

  // Examples with a character buffer (can be used for displays as well)
  sprintf(charbuff, "Now is %02d Hour, %02d Minutes and %02d Seconds. The Epoch is: %10lu" , Hour , Minute, Second, Epoch);
  Serial.println(charbuff);
  sprintf(charbuff, "Today is %3s, %02d %3s %04d ", DayName , Day , MonthName, Year);
  Serial.println(charbuff);
  Serial.println();

  // Examples with Posix expressions
  strftime (charbuff,80,"Now it's %I:%M%p.",timeinfo);
  Serial.println(charbuff);
  Serial.println();
  Serial.println();
  
  delay(1000);
}

It will probably not work on an Arduino without TimeLib.
But frankly, why should we use a much weaker Arduino to do the job, using an ESP anyway over AT serial for the communication?

RIN67630: Now I got it flying for ESP 32 and ESP8266 altogether.

Indeed it runs well.

I wanted to do it better.. and failed again miserabily:

I wanted to replace the manual name tables by the corresponding Posix code.

so I replaced

  DayName   = daysOfTheWeek[Weekday];
  
  MonthName = monthsOfTheYear[Month];

by

  strftime (charbuff,80,"%A",timeinfo);  //cf: https://www.cplusplus.com/reference/ctime/strftime/
  DayName   = charbuff;  // now obsolete:  DayName   = daysOfTheWeek[Weekday];

  strftime (charbuff,80,"%B",timeinfo);
  MonthName  = charbuff; // now obsolete:  MonthName = monthsOfTheYear[Month];

But I got a memory overrun and a reset loop.

".Connected to IP: 192.168.188.075
17:41:47Thanks God, it is: 07/05/2020! Today is 07/05/2020 and Time is 17:41:47
Now is 17 Hour, 41 Minutes and 47 Seconds. The Epoch is: 1588873307
Today is Today is Today is Today is Today is Today is Today is Today is Toda, 07 Today is Today is Today is Today is Today is Today is Today is Today is Toda, 07 Today is Today is 2020 


ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1392, room 16 
tail 0
chksum 0xd0
csum 0xd0
v3d128e5c
~ld
.Connected to IP: 192.168.188.075
17:41:55Thanks God, it is: 07/05/2020! Today is 07/05/2020 and Time is 17:41:55
Now is 17 Hour, 41 Minutes and 55 Seconds. The Epoch is: 1588873315
Today is Today is Today is Today is Today is Today is Today is Today is Toda, 07 Today is Today is Today is Today is Today is Today is Today is Today is Toda, 07 Today is Today is 2020 
"

Why?

It seems to get into trouble here:

// Examples with a character buffer (can be used for displays as well)
 sprintf(charbuff, "Now is %02d Hour, %02d Minutes and %02d Seconds. The Epoch is: %10lu" , Hour , Minute, Second, Epoch);
 Serial.println(charbuff);
 sprintf(charbuff, "Today is %3s, %02d %3s %04d ", DayName , Day , MonthName, Year);
 Serial.print(charbuff);
 Serial.println();

The usage of "Dayname" within sprintf starts something recursive. But "Dayname" is there just a plain variable, not a function? :confused:

DayName and MonthName are declared as char*, so when you set them to charbuff after the strftime() function, the text is not copied from charbuff, the pointers are set to point to the same memory location that is used by charbuff. The sprintf() is therefore taking its input from the same char array as its output when you reference DayName and MonthName.

david_2018:
DayName and MonthName are declared as char*, so when you set them to charbuff after the strftime() function, the text is not copied from charbuff, the pointers are set to point to the same memory location that is used by charbuff. The sprintf() is therefore taking its input from the same char array as its output when you reference DayName and MonthName.

Wow! That was tricky.

Now I have it running well, portable, sleek and verbose:

It will print that in loop:

Thanks God, it is: Thursday! Date is 07/05/2020 and Time is 22:06:24
Now is 22 Hour, 06 Minutes and 24 Seconds. The Epoch is: 1588889184
Date is Thursday, 07 May 2020
Americans say it is 10:06PM, but Europeans prefer using 22:06:24

Here is the code, IMHO read for GitHub:

//**Do not*** #include <TimeLib.h> by Paul Stoffregen, we will mimic it!

#include <NTPClient.h>    // NTP Client by Fabrice Weinberg
#if defined(ESP8266)
#include <ESP8266WiFi.h>  // default from Espressif
#include <WiFiUdp.h>      // default from Espressif  
#elif defined(ESP32)
#include <WiFi.h>         // default from Espressif
#endif

#define WIFI_SSID "SSID"
#define WIFI_PASS "Password"
#define HOST_NAME "ESP-IoT"
#define TZ            2               // (utc+) TZ in hours
#define DST_MN        60              // use 60mn for summer time in some countries
#define GMT_OFFSET_SEC 3600 * TZ      // Do not change here...
#define DAIYLIGHT_OFFSET_SEC 60 * DST_MN // Do not change here...
#define NTP_SERVER "de.pool.ntp.org"

// Variables for Time
static int lastSecond;
tm*        timeinfo;                 //localtime returns a pointer to a tm structstatic int Second;
time_t     Epoch;

static int Second;
static int Minute;
static int Hour;
static int Day;
static int Month;
static int Year;
static int Weekday;
char       DayName[12];
char       MonthName[12];
char       Time[10];
char       Date[12];

static IPAddress ip;

//*** Buffers ***
static char charbuff[80];    //Char buffer for many functions
//String text;                 //String buffer for many functions

// Constructors
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_SERVER, GMT_OFFSET_SEC);

void getWiFi()
{
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while ( WiFi.status() != WL_CONNECTED )
  {
    delay ( 500 );
    Serial.print ( "." );
  }
  ip = WiFi.localIP();
  sprintf(charbuff, "Connected to IP: %03d.%03d.%03d.%03d", ip[0], ip[1], ip[2], ip[3]);
  Serial.println(charbuff);
}

void getNTP()
{
  timeClient.begin();
  timeClient.update();
  Serial.print(timeClient.getFormattedTime());
}
void getEpoch()
{
  Epoch   = timeClient.getEpochTime();
}
void getTimeData()
{
  timeinfo  = localtime(&Epoch);  // cf: https://www.cplusplus.com/reference/ctime/localtime/
  Second    = timeinfo->tm_sec;
  Minute    = timeinfo->tm_min;
  Hour      = timeinfo->tm_hour;
  Weekday   = timeinfo->tm_wday + 1 ;
  Day       = timeinfo->tm_mday;
  Month     = timeinfo->tm_mon + 1;
  Year      = timeinfo->tm_year + 1900; //returns years since 1900
  strftime (DayName , 12, "%A", timeinfo); //cf: https://www.cplusplus.com/reference/ctime/strftime/
  strftime (MonthName, 12, "%B", timeinfo);
  strftime (Time,10, "%T", timeinfo);
  strftime (Date,12, "%d/%m/%Y", timeinfo);
}

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

}
void loop()
{
  timeClient.update();   // should be called from time to time to refresh NTP when expired, does nothing most of the time.
  getEpoch();            // writes the Epoch (Numbers of seconds till 1.1.1970...
  getTimeData();         // breaks down the Epoch into discrete values.

  // Examples with Strings
  Serial.print(F("Thanks God, it is: "));   Serial.print( DayName );
  Serial.print(F("! Date is "));   Serial.print( Date );
  Serial.print(F(" and Time is "));   Serial.println( Time );

  // Examples with a character buffer (can be used for displays as well)
  sprintf(charbuff, "Now is %02d Hour, %02d Minutes and %02d Seconds. The Epoch is: %10lu" , Hour , Minute, Second, Epoch);
  Serial.println(charbuff);
  sprintf(charbuff, "Date is %s, %02d %s %04d ", DayName , Day , MonthName, Year);
  Serial.print(charbuff);
  Serial.println();

  // Examples with Posix expressions
  strftime (charbuff, 80, "Americans say it is %I:%M%p, but Europeans prefer using %T", timeinfo);
  Serial.println(charbuff);
  Serial.println();
  Serial.println();
  delay(1000);
}