ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Well it's impossible to get the month, day, and year from just the day of year, you need the year and day of year.
Anyway, it's a pretty simple process. Generate an array of the last day in each month (31, 28, 31, 30, 31, etc.). Add 1 to February if it's a leap year ((year mod 4 == 0 and year mod 100 != 0) or year mod 400 == 0), take the cumulative sum (31, 59, 90, 121, etc.), and then find where your DOY falls into the list. The month is the index with a last day just above your DOY (+1 if you're using a 0-based language like C), and the day of month is the difference between your DOY and the last DOY of the previous month.
Or you can do it in a loop and subtract the days in each month away from your DOY until the remainder is less than the number of days in the next month. I wrote this up in BASH for my own purposes a while back
Code:
#!/bin/bash
numinputs=$#
if [ $numinputs != 1 ]; then
echo "Usage: what_date YYYYDOY"
exit
else
startdate=$1
fi
startyear=${startdate:0:4}
startdoy=${startdate:4:3}
monthnums=(31 28 31 30 31 30 31 31 30 31 30 31)
test1=`expr $startyear % 4`
test2=`expr $startyear % 100`
test3=`expr $startyear % 400`
if [[ ($test1 == 0 && $test2 != 0) || $test3 == 0 ]]; then
monthnums[1]=29
maxdoy=366
else
maxdoy=365
fi
startdoy=`expr $startdoy + 0`
if [[ $startdoy -gt $maxdoy || $startdoy -lt 1 ]]; then
echo Invalid Date Provided
exit 1
fi
thismon=1
thisday=`expr $startdoy + 0`
while [[ $thisday -gt ${monthnums[$thismon-1]} ]]; do
thisday=`expr $thisday - ${monthnums[$thismon-1]}`
thismon=`expr $thismon + 1`
done
if [[ ${#thismon} == 1 ]]; then
thismon=0$thismon
fi
if [[ ${#thisday} == 1 ]]; then
thisday=0$thisday
fi
echo ${startyear}${thismon}${thisday}
You feed it YYYYDOY and it returns YYYYMMDD. I have one that goes in reverse as well.
Last edited by suicidaleggroll; 02-10-2015 at 12:23 PM.
Well it's impossible to get the month, day, and year from just the day of year, you need the year and day of year.
Anyway, it's a pretty simple process. Generate an array of the last day in each month (31, 28, 31, 30, 31, etc.). Add 1 to February if it's a leap year ((year mod 4 == 0 and year mod 100 != 0) or year mod 400 == 0), take the cumulative sum (31, 59, 90, 121, etc.), and then find where your DOY falls into the list. The month is the index with a last day just above your DOY (+1 if you're using a 0-based language like C), and the day of month is the difference between your DOY and the last DOY of the previous month.
Or you can do it in a loop and subtract the days in each month away from your DOY until the remainder is less than the number of days in the next month. I wrote this up in BASH for my own purposes a while back
Code:
#!/bin/bash
numinputs=$#
if [ $numinputs != 1 ]; then
echo "Usage: what_date YYYYDOY"
exit
else
startdate=$1
fi
startyear=${startdate:0:4}
startdoy=${startdate:4:3}
monthnums=(31 28 31 30 31 30 31 31 30 31 30 31)
test1=`expr $startyear % 4`
test2=`expr $startyear % 100`
test3=`expr $startyear % 400`
if [[ ($test1 == 0 && $test2 != 0) || $test3 == 0 ]]; then
monthnums[1]=29
maxdoy=366
else
maxdoy=365
fi
startdoy=`expr $startdoy + 0`
if [[ $startdoy -gt $maxdoy || $startdoy -lt 1 ]]; then
echo Invalid Date Provided
exit 1
fi
thismon=1
thisday=`expr $startdoy + 0`
while [[ $thisday -gt ${monthnums[$thismon-1]} ]]; do
thisday=`expr $thisday - ${monthnums[$thismon-1]}`
thismon=`expr $thismon + 1`
done
if [[ ${#thismon} == 1 ]]; then
thismon=0$thismon
fi
if [[ ${#thisday} == 1 ]]; then
thisday=0$thisday
fi
echo ${startyear}${thismon}${thisday}
You feed it YYYYDOY and it returns YYYYMMDD. I have one that goes in reverse as well.
I was having lunch.
thank you for your information... it is really an amazing post !!!!!!!!!
It is really clearly writen !!!!!!!! Lovin' it
I will try to reverse this one - using the loop method...
Code:
int leap(int y)
{
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}
int main() {
int year=1992;
int month=12;
int day=1;
int mo[12] = {31,28+leap(year),31,30,31,30,31,31,30,31,30,31};
int i;
int dofy=0; // EDIT
for (i=0; i<(month-1); i++) {
dofy += mo[i];
}
dofy += day;
printf("%d\n", dofy);
return 0;
}
How would you propose using mktime()? Quote from the manpage:
"The mktime() function converts a broken-down time structure, expressed as local time, to calendar time representation. The function ignores the values supplied by the caller in the tm_wday and tm_yday fields."
The heart of the code is only ~6 lines long (setting up the array of days in each month, checking for a leap year, and a tiny little while loop). The rest is just I/O formatting and error checking, which if this is a C function with integer I/O should be either irrelevant or much simpler. I would be surprised if the C function was more than 10 lines long. I thought a minute and a half per line was being generous, considering you already have an example to work off of.
The heart of the code is only ~6 lines long (setting up the array of days in each month, checking for a leap year, and a tiny little while loop). The rest is just I/O formatting and error checking, which if this is a C function with integer I/O should be either irrelevant or much simpler. I would be surprised if the C function was more than 10 lines long. I thought a minute and a half per line was being generous, considering you already have an example to work off of.
Either way, good luck with it.
many thanks.
The way you explained it, above, was really clean and very clearly explained step by step.
Although... I read it at least 5 times on my iphone to get it.
I had still difficulties to understand the leap days - why to use an array. As soon as I can - time -, I'll progress on the code. Time is the key of everything, right? -not necessarily
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.