Print current date, without complex time commands - c

The prompt is:
Implement a function that determines and prints out the current year, month and day.
For example:
Today is 03/04/2014.
You guys dont have to really mind the code i wrote, its just kinda like scribble trying to figure our a way to print the current date using the seconds since the epoch given by the
time(NULL) command.
Before anyone gives me a super complex time command code etc etc, im pretty sure my professor wants us to convert the unix time (seconds since the epoch: jan 1, 1970) to the current date somehow.
Would anyone be able to help me in anyway to do this in the way my professor wants?
Thanks!
The code i currently have is:
#include <stdio.h>
#include <time.h>
int main ()
{
int days, weeks, months, years, option, rmd, currentyear, currentmonth;
time_t seconds;
seconds = time(NULL);
days = seconds/(60*60*24);
weeks = seconds/((60*60*24)*7);
rmd=seconds%31557600;
months = ((seconds/31557600) * 12)+(((float)rmd/31557600)*12);
years = days/(365.25);
currentyear = 1970 + years;
currentmonth = (((float)rmd/31557600)*12)+1;
printf("%ld/%ld", currentmonth,currentyear);
;
return 0;
}

#include <stdio.h>
#include <time.h>
int main(void)
{
time_t now = time(0);
struct tm *t = localtime(&now);
printf("%.4d-%.2d-%.2d\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
return 0;
}

Dealing with dates the naive way is a suicide*, use the localtime function. It will still get something wrong (dates are a horrible hideous mess that just cannot be got completely right), but at least the "nornal" stuff is already taken care of, and it's someone else's fault anyhow.
*your code is not handling leap years, so your result is completely wrong. So you add the code to check for years multiple if four. But then dates before 1900 are wrong, because century boundaries are an exception (they aren't leap years). And then dates after 2000 are all wrong, because there's an exception to the exception, and years divisible by 400 are leap years anyway. And we haven't started talking about time zones, DST and leap seconds.

Related

Time not printing on command line when compiled

I'm trying to run the below code. I'm compiling like so.
gcc -o time time.c
Instead of getting my desired output, the current time of day, hor minute, year, etc.
Today is : Thu Oct 31 02:01:37 2019
Time is : 02:01:37 am
Date is : 31/10/2019
I'm getting this instead. I've tried a variety of different time functions similar to this and I keep getting this below output instead of what I want.
real 0m0.000s
user 0m0.000s
sys 0m0.000s
I'm sure this is really simple, can anyone point me in the right direction?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Print current date and time in C
int main(void){
// variables to store date and time components
int hours, minutes, seconds, day, month, year;
// time_t is arithmetic time type
time_t now;
// Obtain current time
// time() returns the current time of the system as a time_t value
time(&now);
// Convert to local time format and print to stdout
printf("Today is : %s", ctime(&now));
// localtime converts a time_t value to calendar time and
// returns a pointer to a tm structure with its members
// filled with the corresponding values
struct tm *local = localtime(&now);
hours = local->tm_hour; // get hours since midnight (0-23)
minutes = local->tm_min; // get minutes passed after the hour (0-59)
seconds = local->tm_sec; // get seconds passed after minute (0-59)
day = local->tm_mday; // get day of month (1 to 31)
month = local->tm_mon + 1; // get month of year (0 to 11)
year = local->tm_year + 1900; // get year since 1900
// print local time
if (hours < 12) // before midday
printf("Time is : %02d:%02d:%02d am\n", hours, minutes, seconds);
else // after midday
printf("Time is : %02d:%02d:%02d pm\n", hours - 12, minutes, seconds);
// print current date
printf("Date is : %02d/%02d/%d\n", day, month, year);
return 0;
}
It seems to me you are calling the time command somehow, rather than your program.
Typically you will want to do:
./time
Instead of:
time

How to print a future time from system time in C. Such as if it is 10 am now, to print 12 am instead

I am currently learning C programming and i am trying to out put a time for the next scheduled flight of a mock airport. i though i could use the system time, then have that be modified so it out puts which ever time is 3 hours from that moment. However, i could only find solutions to out put the current time on the system. Any help would be appreciated.
I've tried a few different methods I've seen others do, but have had no luck in modifying them as of yet. I am still very new to C programming, so i cant read many of these functions, and due to that cannot find where in them to edit or change out in order to achieve the desired result.
#include<stdio.h>
#include<time.h>
int main(){
time_t t;
time(&t);
printf("\n right now the time is: %s",ctime(&t));
}
this outputs to "Mon Aug 12 10:00:17 2019"
my end goal is something similar to "12:00 pm" if the current time is 10 am
In t the seconds since the unix epoch (1970-01-01 00:00 UTC) is stored.
So you can simply add 3h = 3600*3 = 10800 to it:
time_t t;
time(&t);
t += 10800;
printf("\n In 3 hours the time is: %s",ctime(&t));
Since flights are every 3 hours, I take be modified so it out puts which ever time is 3 hours from that moment. to mean up to 3 hours from the current moment.
If so,
1) Avoid making the non-portable assumption the time_t is in seconds.
2) Convert to local time, do the math on the .tm_hour member.
time_t t;
if (time(&t) == -1) Handle_invalid_time();
printf("Right now the time is: %s",ctime(&t));
struct tm *tm = localtime(&t);
if (tm == NULL) Handle_invalid_conversion();
tm->tm_hour += 3;
tm->tm_min = 0;
tm->tm_sec = 0;
// re-adjust members to their usual range (Handle going into next, day, month, year)
mktime(tm);
printf("Flight time: %s", asctime(tm));

time(time_t *timer) gives wrong results without time drift in system

below code is for doing some stuff and sleep till next interval.
for calculation of sleep time, I am using below logic.
time_t start = time(0);
time_t end = time(0);
int timeLeft = 0;
int interval = 300;
while(1)
{
/* do something
* lets say takes 5 to 20 seconds to execute
*/
end = time(0);
timeLeft = interval -(end - start);
printf("timeLeft: %d, interval: %d, end: %u, start: %u",timeLeft,interval,end,start);
sleep(timeLeft)
start = time(0);
}
After an uptime of 34 hours of the system, timeLeft is coming as greater than 300, which should never happen.
I have checked, there is no time drift in the system.
for an instance, when the issue happened,
timeLeft: 11484, interval: 300, end: 1549402241, start: 1549413425
Don't know how can above happen?
need help.
This analysis of the issue doesn't actually give a single answer, but it was too long to fit in a comment so here goes.
After looking at your code, it appears that the problem is that end < start. But end = time(0) is always called after start = time(0).
Your example assumes that you can subtract time_t values and get the elapsed seconds between them, but the C standard does not guarantee that. Your code seems to be running on a recent version of Linux so I took a look at the GNU Libc manual, and apparently time returns the number of secs since 00:00:00 on January 1, 1970, and a time_t is a long int. I also checked the values of start and end, when the issue occurred, and their values are about 49 years worth of secs, and since it been 49 years since January 1, 1970, it appears that the assumption in your example is valid.
My best guess is that there is some significant difference between the actual code and your example. Perhaps a call to start = time(0) that takes place after the call to end=time(0), or maybe situations where a call to end=time(0) does not take place.
You can rule this out by converting your example into an actual program and see if that program has the same issue. If it does, you can post the code for the program. This site encourages people to create Minimal, Complete, and Verifiable examples.
In the meantime, I can make some other guesses:
Your program has more than one thread, and your threads are stepping on each other.
Some weird compiler optimization is causing the calls to time(0) to be moved around.

C - calculate all dates from Year X to Year Y

Please IGNORE, incompetence as its best!
Just messing with some basic file i/o really, in some nested for Loops but the output isn't quite what I want, though I can't seem to get it working.
#include <stdio.h>
int main(void) {
FILE *pFile;
pFile = fopen("dates.txt", "w");
int day, month, year;
for(day = 1; day <= 31; day++) {
for(month = 1; month <= 12; month++) {
for(year = 1900; year <= 2050; year++) {
if(day < 10 && month < 10) {
fprintf(pFile, "0%d/0%d/%d\n", day, month, year);
}else {
fprintf(pFile, "%d/%d/%d\n", day, month, year);
}
}
}
}
return 0;
}
Any tips much appreciated! And as a heads up, this isn't an homework task, just some experimentation really.
Cheers.
You can use mktime to create a date. Then add 1 day to it and create the next date.
This way you can iterate.
Following code shows first 200 dates.
#include <time.h>
#include <stdio.h>
int main(){
struct tm *lt;
int i=200;
//time_t t=0; // first second on epoch
time_t t=-2209010000; // first second on 1900 (works on GCC, dind't test MSVS compiler)
while(i--){
lt = localtime(&t);
printf("YYYY:MM:DD = %04d:%02d:%02d\n", lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday);
lt->tm_hour+=24; // adding 24 hours
t = mktime(lt);
}
return 0;
}
By the way it works dates behind epoch. At least on my gcc version 4.4.3 in x86_64 GNU/Linux
You can actually have 4 combinations of day and month in which you may or may not prefix with 0, which you are trying to handle with single if else.
Case 1: Both day and month <10, handled by first if.
Case 2: Day > 10 and Month < 10, un-handled
Case 3: Day < 10 and Month > 10, un-handled
Case 4: Both are > 10. Handled in else.
%02d is the option to handle all the cases.
You probably want the year loop before the month loop before the day loop (the reverse of the current order).
You are going to need to make the testing for maximum day of the month cleverer (you need to know the rules for leap years (noting that 1900 was not a leap year, pace MS Excel, and 2000 was).
You can use %02d or %.2d to print 2 digits for the month and day, so you only need a single printf() statement.

How to decompose unix time in C

This seems like something no one should ever have to do, but I'm working on a kernel module for an embedded system (OpenWRT) in which it seems that time.h does include the timespec and time_t types, and the clock_gettime and gmtime functions, but does not include localtime, ctime, time, or, critically, the tm type.
When I attempt to cast the return pointer from gmtime to my own struct, I get a segfault.
So I guess I'd be content to solve the problem either of two ways—it'd be great to figure out how to get access to that missing type, or alternatively, how to roll my own method for decomposing a unix timestamp.
This should be accurate (fills out a cut-down imitation of a struct tm, my year uses Common Era instead of a 1900 CE epoch):
struct xtm
{
unsigned int year, mon, day, hour, min, sec;
};
#define YEAR_TO_DAYS(y) ((y)*365 + (y)/4 - (y)/100 + (y)/400)
void untime(unsigned long unixtime, struct xtm *tm)
{
/* First take out the hour/minutes/seconds - this part is easy. */
tm->sec = unixtime % 60;
unixtime /= 60;
tm->min = unixtime % 60;
unixtime /= 60;
tm->hour = unixtime % 24;
unixtime /= 24;
/* unixtime is now days since 01/01/1970 UTC
* Rebaseline to the Common Era */
unixtime += 719499;
/* Roll forward looking for the year. This could be done more efficiently
* but this will do. We have to start at 1969 because the year we calculate here
* runs from March - so January and February 1970 will come out as 1969 here.
*/
for (tm->year = 1969; unixtime > YEAR_TO_DAYS(tm->year + 1) + 30; tm->year++)
;
/* OK we have our "year", so subtract off the days accounted for by full years. */
unixtime -= YEAR_TO_DAYS(tm->year);
/* unixtime is now number of days we are into the year (remembering that March 1
* is the first day of the "year" still). */
/* Roll forward looking for the month. 1 = March through to 12 = February. */
for (tm->mon = 1; tm->mon < 12 && unixtime > 367*(tm->mon+1)/12; tm->mon++)
;
/* Subtract off the days accounted for by full months */
unixtime -= 367*tm->mon/12;
/* unixtime is now number of days we are into the month */
/* Adjust the month/year so that 1 = January, and years start where we
* usually expect them to. */
tm->mon += 2;
if (tm->mon > 12)
{
tm->mon -= 12;
tm->year++;
}
tm->day = unixtime;
}
My apologies for all the magic numbers. 367*month/12 is a neat trick to generate the 30/31 day sequence of the calendar. The calculation works with years that start in March until the fixup at the end, which makes things easy because then the leap day falls at the end of a "year".
In userspace glibc will do a lot of work with regards to handling the "local" part of time representation. Within the kernel this is not available. Probably you should not try to bother with this within your module, if needed do it in userspace.
A time_t is the number of seconds since Jan 1, 1970 UTC so decomposing that into month, day, and year isn't that difficult provided that you want the result in UTC. There is a bunch of source available by Googling "gmtime source". Most embedded systems leave out local time processing since it is a little more difficult due to the reliance on timezone setting and the environment.

Resources