LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-10-2015, 12:06 PM   #1
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Rep: Reputation: 255Reputation: 255Reputation: 255
C: determine date from day of year?


Hello

I have a number that is the day of the year.

I know :
http://rosettacode.org/wiki/Day_of_the_week
What I need is sort to say the way around.

I would like to determine the date (yy , mm, dd) from the day of the year (one single integer).

(WITHOUT using MKTIME)

Have you a possible code?

Thank you

Last edited by Xeratul; 02-10-2015 at 12:27 PM.
 
Old 02-10-2015, 12:09 PM   #2
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Original Poster
Rep: Reputation: 255Reputation: 255Reputation: 255
I got this but it is into java :
http://stackoverflow.com/questions/4...-in-javascript
 
Old 02-10-2015, 12:18 PM   #3
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
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.
 
2 members found this post helpful.
Old 02-10-2015, 12:28 PM   #4
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Original Poster
Rep: Reputation: 255Reputation: 255Reputation: 255
For instance: I give 2015 and day of year: 41.


and I would expect that the C code give me: 10.februar 2015!
 
Old 02-10-2015, 12:49 PM   #5
mina86
Member
 
Registered: Aug 2008
Distribution: Debian
Posts: 517

Rep: Reputation: 229Reputation: 229Reputation: 229
Quote:
Originally Posted by Xeratul View Post
For instance: I give 2015 and day of year: 41.

and I would expect that the C code give me: 10.februar 2015!
suicidaleggroll has described how to do that. What else do you need? If you have problems show us what you’ve came up so far.
 
Old 02-10-2015, 02:21 PM   #6
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Original Poster
Rep: Reputation: 255Reputation: 255Reputation: 255
Quote:
Originally Posted by suicidaleggroll View Post
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;
}
 
Old 02-11-2015, 01:53 AM   #7
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
Not using mktime?

So this is homework or an interview question?
 
Old 02-11-2015, 06:10 AM   #8
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 447Reputation: 447Reputation: 447Reputation: 447Reputation: 447
Yes, maybe solution without dependecies is wanted? If not, a simpler solution with date command:

Code:
date -d '2015-01-01 + 40 days'
 
Old 02-11-2015, 09:08 AM   #9
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: Rocky Linux
Posts: 4,779

Rep: Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212
Quote:
Originally Posted by bigearsbilly View Post
Not using mktime?
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."
 
Old 02-11-2015, 11:13 AM   #10
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Original Poster
Rep: Reputation: 255Reputation: 255Reputation: 255
Quote:
Originally Posted by bigearsbilly View Post
Not using mktime?

So this is homework or an interview question?

(1)
ah ah. I shall certainly not reply your question. I am sorry.
Please re-focus on the topic of the thread.

(2) I would like not to use mktime such as tm_wday,...
I am wishing to find a method using not tm_wday,... due to various reasons.


As indicated above, it is possible, not easy, but definitely possible.
I can make it within 1-4 hours, but I havent got the ressource yet.
 
Old 02-11-2015, 11:20 AM   #11
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
Not easy? It's one of the easiest things you can do in programming. It should take 15 minutes tops if you have any programming experience.
 
Old 02-11-2015, 11:59 AM   #12
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Original Poster
Rep: Reputation: 255Reputation: 255Reputation: 255
Quote:
Originally Posted by suicidaleggroll View Post
Not easy? It's one of the easiest things you can do in programming. It should take 15 minutes tops if you have any programming experience.
Well, slow mind maybe. I am not so talented.
I can definitely make it but I might take longer than 15 minutes - surely.

Do you think that 15 minutes is really without big coding experience?
Your code in bash is pretty nice and clear - respect!
 
Old 02-11-2015, 12:11 PM   #13
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
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.
 
Old 02-11-2015, 12:17 PM   #14
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Original Poster
Rep: Reputation: 255Reputation: 255Reputation: 255
Quote:
Originally Posted by suicidaleggroll View Post
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
 
Old 02-11-2015, 12:20 PM   #15
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
Quote:
Originally Posted by Xeratul View Post
I had still difficulties to understand the leap days - why to use an array.
The only array is the number of days in each month, I'm not sure how you'd do it any other way. The leap day is only added to February when necessary.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Get day of the year for a specific date SmurfGGM Linux - General 3 12-18-2013 06:21 PM
[SOLVED] ERROR: Date::Manip unable to determine TimeZone. ewalter Linux - Newbie 2 06-29-2012 02:58 PM
It's that day of the year again rsciw General 2 07-30-2010 08:43 AM
Determine date when linux was installed twantrd Linux - General 4 05-16-2005 10:00 PM
ls sometimes year sometimes the time of day suguru Linux - Software 1 02-18-2004 10:27 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:10 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration