GMT time to Seconds - c

I am implementing a cache in a proxy server. I am storing Expires: field from the response of request and next time if same request comes then i will compare the Expires time with current time.
Now I am stuck here. how should I convert Expire time format to seconds and then take a difference?
Is that any other way to get time difference ?
Format for Expire time is :
Sat, 10 Nov 2012 07:05:26 GMT
Suppose I have two time, how can I compare two times in GMT?

Here's a working example :
#include <stdio.h>
#include <time.h>
int main(int argc, char **argv) {
struct tm t;
time_t seconds;
const char *expire = "Sat, 10 Nov 2012 07:05:25 GMT";
strptime(expire, "%a, %d %B %Y %H:%M:%S", &t);
seconds = mktime(&t);
printf("%lu\n", seconds);
}
Note that your times must be in GMT time since strptime() ignores the time zone (at least on Linux). You may also need to set your locale to the same locale used for your input times.

If your implementation has it, you could use the strptime function to convert that string to a struct tm, then mktime to convert that to a time_t for easy comparison.

Related

C - mktime altering passed time_t value

I need the functionality for a user to enter a timestamp, store that timestamp on the disk, then display that timestamp at a later time. I also need to be able to determine the distance between two timestamps.
My current solution is to use the time.h utility as follows:
To read a given timestamp of the form "MO/DA/YEAR HR:MI"
time_t readable_to_epoch(char* str) {
int mo, da, yr, hr, mi;
sscanf(str, "%d/%d/%d %d:%d", &mo, &da, &yr, &hr, &mi);
struct tm timeinfo;
time_t out;
timeinfo.tm_mon = mo - 1;
timeinfo.tm_mday = da;
timeinfo.tm_year = yr - 1900;
timeinfo.tm_hour = hr;
timeinfo.tm_min = mi;
timeinfo.tm_sec = 0;
out = mktime(&timeinfo);
return out;
}
To convert a given time_t into a human readable form:
// WARNING returned string must be freed;
char* epoch_to_readable(time_t time) {
return asctime(localtime(&time));
}
My issue is that if I pass in the input:
06/19/2018 12:52
The conversion to time_t and back is as desired. Here is the test harness output:
original: 06/19/2018 12:52
epoch time: 1529437920
converted readable: Tue Jun 19 12:52:00 2018
But when I pass in the input:
01/01/2022 10:00
The converted readable seems to be one hour behind:
original: 01/01/2022 10:00
epoch time: 1641056400
converted readable: Sat Jan 1 09:00:00 2022
I have no idea why this is happening, and google isn't helping. What do I need to do to fix this?
You did not set timeinfo.tm_isdst, so you're getting undefined behaviour. You should use -1.
Daylight Saving Time flag. The value is positive if DST is in effect, zero if not and negative if no information is available
Note that working with local times without offset is inherently buggy. Because of Daylight Saving Time, time stamps from two hours each year are indistinguishable from each other.

How to compare GMT time and local time in C?

my server uses local time of Prague (+ 2 hours) and visitor's request uses GMT time.
In code I want to compare these times but for that I need to convert them to the same time zone. How to do it? When I try to use gmtime() and localtime() they returns same result.
struct tm time;
struct stat data;
time_t userTime, serverTime;
// this time will send me user in GMT
strptime("Thu, 15 Apr 2021 17:20:21 GMT", "%a, %d %b %Y %X GMT", &time)
userTime = mktime(&time); // in GMT
// this time I will find in my server in another time zone
stat("test.txt", &data);
serverTime = data.st_mtimespec.tv_sec; // +2 hours (Prague)
// it's not possible to compare them (2 diferrent time zones)
if(serverTime < userTime) {
// to do
}
Thank you for answer.
On linux with glibc you can just use %Z with strptime to read GMT.
#define _XOPEN_SOURCE
#define _DEFAULT_SOURCE
#include <time.h>
#include <assert.h>
#include <string.h>
#include <sys/stat.h>
#include <stdio.h>
int main() {
// this time will send me user in GMT
struct tm tm;
char *buf = "Thu, 15 Apr 2021 17:20:21 GMT";
char *r = strptime(buf, "%a, %d %b %Y %X %Z", &tm);
assert(r == buf + strlen(buf));
time_t userTime = timegm(&tm);
// this time represents time that has passed since epochzone
struct stat data;
stat("test.txt", &data);
// be portable, you need only seconds
// see https://pubs.opengroup.org/onlinepubs/007904875/basedefs/sys/stat.h.html
time_t serverTime = data.st_mtime;
// it's surely is possible to compare them
if (serverTime < userTime) {
// ok
}
}
// it's not possible to compare them (2 diferrent time zones)
But it is!
The time that has passed since an event can't be in a timezone. Count of seconds since epoch is how many seconds have passed since that event, it's relative time that has passed, it's distance in time. No matter in which timezone you are, no matter if daylight saving time or not, the time that has passed since an event is the same in every location (well, excluding relativistic effects, which we don't care about). Timezone is irrelevant. mktime returns the number of seconds since epoch. stat returns timespec which represents time that have passed since epoch. Timezone has nothing to do here. Once you represent time as relative to some event (ie. since epoch), then just compare them.

Getting UTC time as time_t

I am trying to get UTC time as time_t.
Code below seems giving it correct but surprisingly prints local time only:
time_t mytime;
struct tm * ptm;
time ( &mytime ); // Get local time in time_t
ptm = gmtime ( &mytime ); // Find out UTC time
time_t utctime = mktime(ptm); // Get UTC time as time_t
printf("\nLocal time %X (%s) and UTC Time %X (%s)", mytime, ctime(&mytime), utctime, ctime(&utctime));
As we can see values of mytime and utctime we get are different.
However, when passed as parameters to ctime it converts them to same string.
Local time 55D0CB59 (Sun Aug 16 23:11:45 2015) and UTC Time 55D07E01
(Sun Aug 16 23:11:45 2015)
By definition the C time() function returns a time_t epoch time in UTC. So the code commented "//get the local time in time_t" is really getting UTC already, and the comment is incorrect.
From the Linux man-page:
time_t time(time_t *tloc);
time() returns the time as the number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
Giving the code:
#include <time.h>
...
time_t utc_now = time( NULL );
The ctime result is a static variable. Do not use ctime twice in the same print statement. Do it in two separate print statements.
If ctime is replaced with asctime, the same problem will arise as asctime also returns the result as a static variable.
That's exactly what the documented behavior is supposed to do:
Interprets the value pointed by timer as a calendar time and converts it to a C-string containing a human-readable version of the corresponding time and date, in terms of local time.
You probably want to use asctime instead.
ctime function returns a C string containing the date and time information in a human-readable format.
To get time in UTC you can use gettimeofday() (for Linux)-
struct timeval ptm;
gettimeofday(&ptm,NULL);
long int ms = ptm.tv_sec * 1000 + ptm.tv_usec / 1000;
And you can see function GetSystemTime in for windows.

converting milliseconds to date in C

Is there any way of converting milliseconds to date in C?
What I am trying to do is write a small application in C that can return the financial year and the like(quarter, week) given the start month and isCurentYear bool, where the input might be milliseconds or a date!
In the first place, is there any way by which this can be achieved in C?
And if so, in the process of finding out a way of converting milliseconds to date
I have found out that the use of time_t takes the current millis of our system and by creating a structure pointing to it,it permits us to extract the year,month, date, sec etc!
Refer the below code:
#include <sys/time.h>
#include<stdio.h>
#include<time.h>
void main()
{
time_t t = time(000);
//time_t t = time(0);
struct tm tm = *localtime(&t);
printf("now: %d-%d-%d %d:%d:%d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
And also, can time_t be used to store millisecond values so that it can be converted to date using tm struct?
Function time_t time(time_t* timer) returns the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC. In addition, if the input argument timer != NULL, then the function also sets this argument to the same value (so you probably have no reason to call it with anything else but NULL).
Function struct tm* localtime(const time_t* timer) takes the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC, and returns a structure that represents the equivalent time & date. If you're working on a multi-threaded application, then please note that this function is not thread safe.
As to your question - is there any way for converting milliseconds to time & date - yes, but:
Take into consideration that the milliseconds will be considered as of 00:00 hours, Jan 1, 1970 UTC.
Since the time_t type is 32-bit long, you will not be able to convert 4G*1000 milliseconds or more.
Here is a function for converting milliseconds to time & date:
struct tm* GetTimeAndDate(unsigned long long milliseconds)
{
time_t seconds = (time_t)(milliseconds/1000);
if ((unsigned long long)seconds*1000 == milliseconds)
return localtime(&seconds);
return NULL; // milliseconds >= 4G*1000
}
For those of us who were searching the web for an answer to apply to embedded c applications, think pic 32 programming here is the mathematical calculation:
Date in Epoch_seconds = ( (epoch_seconds / 1000) / 86400 ) + 25569
Resulting in a 5 digit answer which is 10 bits long format dd/MM/yyyy
(Note: the slashes are encoded in the result here so when converting to human readable date please account for it)
Where one day = 86400 ms
and the date 1970/1/1 = 25569
example:=( (1510827144853/1000) / 86400 ) + 25569 = 43055
put 43055 in excel and format cell to date dd/MM/yyyy and it gives you 16/11/2017
Perhaps, you are looking for strftime function.
char text[100];
time_t now = time(NULL);
struct tm *t = localtime(&now);
strftime(text, sizeof(text)-1, "%d %m %Y %H:%M", t);
printf("Current Date: %s", text);

time(NULL) returning different time

I am trying to get current time in C using time_t current_time = time(NULL).
As I understand, it would return me the current time of system.
I am later trying to convert it into GMT time using struct tm* gmt = gmtime(&current_time).
I print both times using ctime() and asctime() functions.
The current time on my system is GMT + 1. But gmtime() returns me the same time as current_time is. I could not understand why gmtime() is returning me same time. Any help will be appreciated.
Ok here is the code and the output: Current time that windows is showing is 17:54 (Stockholm zone; GMT+1). I want something to return me 15:54. Or perhaps my understanding is wrong ...
time_t current_time = time(NULL);
struct tm* gmt = gmtime(&current_time);
struct tm* loc = localtime(&current_time);
printf("current time: %s\n", ctime(&current_time));
printf("gmt time %s\n", asctime(gmt));
printf("local time %s\n", asctime(loc));
Output:
current time: Mon Oct 8 17:54:06 2012
gmt time Mon Oct 8 17:54:06 2012
local time Mon Oct 8 17:54:06 2012
Accepted Solution: From Simes
That's probably your problem. Check the value of your TZ environment variable; if not present, it will default to GMT. Cygwin doesn't automatically pick up the time zone setting from Windows. See also localtime returns GMT for windows programs running on cygwin shells
A time_t type holds a value representing the number of seconds since the UNIX epoch.
A tm type holds a calendar value.
gmtime() just converts system time (which is always UTC) from time_t to tm. That's why the values are the same. If you want a representation of your local time (GMT+1), that's what localtime() is for.
time() returns the number of seconds since epoch. Which is equal to UTC (aka GMT)
Epoch was 1.1.1970, 00:00:00 in Greenwich, UK.
So in fact time() does not return a time, but a time difference.
Run the debugger over these two lines:
struct tm* gmt = gmtime(&current_time);
struct tm* loc = localtime(&current_time);
Break on the second line, watch members of gmt and when you execute the second line - you will see that some gmt members change value. Apparently some static memory is used by the library. So save the results of the first statement before running the second

Resources