Localtime VS Localtime_S and Appropriate Input Arguments

Using localtime_s to create a timestamp? And using asctime_s. C++

The first problem is you are not passing enough arguments to localtime_s. It requires two arguments but you are only passing one. The first argument should be a pointer to tm and the second a pointer to a time_t. The second problem is that the return type is errno_t not a pointer to tm. Your code for acquiring the current time should actually be:

time_t rawtime;
tm timeinfo;
errno_t result = localtime_s(&timeinfo, &rawtime);

There is also a problem with sending the current time to cout. Since there is no overloaded version of operator<< that takes a type tm you will get the value of the pointer instead of the text representation of the time. After applying the above changes you will also need to change the stream out line from:

cout << "Current local time and date: " << timeinfo << endl;

to:

cout << "Current local time and date: " << asctime(&timeinfo) << endl;

Any time you encounter a problem like this you should either look at the function signature or refer to the documentation to determine how to properly call the function. The documentation usually details what the arguments are, what values they can be (i.e. if NULL is acceptable for pointers), and what their return values are (if any). in this case the return value represents an error condition and should be checked to determine if the call was successful.

localtime and asctime are unsafe, but the safe functions don't have the same parameters

The reason those functions have different parmaters is that the lack of safety is caused by only have a single parameter. In particular, asctime() uses a single buffer to return the time. So if you do something like:

char *s1 = asctime((time_t)0);   // 1-Jan-1970 00:00:00 or something like that. 
time_t t = time();
char *s2 = asctime(t);
cout << "1970: " << s1 << " now:" << s2 << endl;

Then you will not see two different times printed, but the current time printed twice, as both s1 and s2 point to the same string.

The same applies to localtime, which returns a pointer to struct tm - but it's always the same struct tm, so you if you do:

struct tm* t1 = localtime(0);
struct tm* t2 = localtime(time());

you will get the same values in t1 and t2 (with the "current" time, not 1970).

So, to fix this problem, asctime_s and localtime_s have an extra parameter that is used to store the data into. asctime_s also have a second extra parameter to tell the function how much space there is in the storage buffer, as otherwise, it could overflow that buffer.

get current date with localtime_s

The time_t variable should be initialized with time(&rawtime) such that localtime_s can use it to properly fill out the struct. Much like your very first line time_t t = time(0), it's required that you initialize the variable with the time function and pass it a null parameter (0) or a pointer to the variable (&rawtime).

Unfortunately allocating a time_t var within memory does not automatically calculate the time since Epoch. Here's a question that addresses the same problem, except it has an example of the code you're looking for.

Can I use another way to get the time from C++?

If you are willing to install Howard Hinnant's free, open-source tz library, then GetTime() can be simplified down to:

#include "tz.h"
#include <string>

std::string
GetTime()
{
using namespace std::chrono;
using namespace date;
return format("[%X]:", make_zoned(current_zone(), system_clock::now()));
}

This just output for me:

[10:42:32]:

Here are the installation directions (including for Windows).

Error code with implementation of time_t in C++

C4996 isn't supposed to be an error, I suppose you adjusted your compile options to make it one. (Or the project wizard did)

Anyway, the alternate functions that don't use static local buffers ARE better, and they're also portable (in everything except the name, it's localtime_s on Win32 and localtime_r on Linux, which a macro can fix), so there's really no reason not to use them.

The versions without static local buffer expect you to supply a buffer, which is easy:

time_t rawtime;
struct tm timeinfo; // no longer a pointer

time(&rawtime);

// on platforms with POSIX localtime_r but no localtime_s, add this macro
// #define localtime_s(x, y) localtime_r(y, x)
localtime_s(&timeinfo, &rawtime); // fills in your structure,
// instead of returning a pointer to a static one

heure_= timeinfo.tm_hour; // no longer using a pointer
minute_ = timeinfo.tm_min;
seconde_ = timeinfo.tm_sec;
jourMois_ = timeinfo.tm_mday;
jourSemaine_ = timeinfo.tm_wday;
mois_ = timeinfo.tm_mon;
annee_ = timeinfo.tm_year;

Cant get right localtime in C

tl;dr If you want the time at a location, you have to set TZ to a location.


1634224877 is 2021-10-14 15:21:17 UTC. setenv takes POSIX time zones which don't work like you think. UTC+1 means one hour head of UTC. That is 14:21:17. If you want "UTC+1" you actually ask for UTC-1, one hour behind UTC.

But don't ask for UTC-1.



setenv("TZ", "UTC+1", 1); // Italy is UTC+1

That comment is not correct. Italy is not UTC+1. Sometimes Italy is UTC+1, sometimes it is UTC+2. In order to know about daylight savings time (and other wacky time zone issues), TZ needs to know your location.

Set TZ to the city closest to you, like Europe/Rome. Now localtime can figure out whether it's daylight savings time or not, you do not need to correct it.

int main()
{
setenv("TZ", "Europe/Rome", 1);
tzset();

time_t sec = 1634224877; // Just for test

struct tm * end = localtime(&sec);

printf("Daylight savings time?: %d\n", end->tm_isdst);

printf("Time is says: %.2d/%.2d/%d - %.2d:%.2d:%.2d\n", end->tm_mday, end->tm_mon + 1, end->tm_year + 1900,
end->tm_hour, end->tm_min, end->tm_sec);
}

Daylight savings time?: 1
Time is says: 14/10/2021 - 17:21:17

The system that manages time zones is called tzdata. It is a database of locations, their time zone information, daylight savings time switches, and a host of other wacky time zone information. It's what lets your computer know that Rome is usually UTC+1 but should sometimes be UTC+2.

A list of all tzdata locations can be had on Wikipedia, but these do not necessarily match the tzdata installed on your machine.



Related Topics



Leave a reply



Submit