Operating System - Linux
1752795 Members
6638 Online
108789 Solutions
New Discussion юеВ

Re: Three-Digit Day of Year

 
SOLVED
Go to solution
Michael Leis
Advisor

Three-Digit Day of Year

I need help with a unix shell script (prefer K-shell) that will convert a given date in the format yyyymmdd into yyddd. (Input format is negotiable, output format needs to be yyddd or yy seperated from ddd.) For example, I put in 20050831 it would output 05243 because August 31 was the 243 day of 2005. I'm familiar with date '+%y%j' that provides that for todays date, but I need to be able to declare any reasonable given date in the past or future. I don't want the true julian date (number of days since 4713BC), just the number of days a given date is into its year. Any help is appreciated.
11 REPLIES 11
Pete Randall
Outstanding Contributor

Re: Three-Digit Day of Year

Sounds like a job for Clay's caljd.sh (attached). Invoke as "caljd.sh -u" for usage details.


Pete

Pete
Pete Randall
Outstanding Contributor

Re: Three-Digit Day of Year

Michael,

I apologise - I assumed that Clay's script would handle such a thing but, going through the usage notes myself, I don't see an option for 3 digit output.


Pete

Pete
Pete Randall
Outstanding Contributor

Re: Three-Digit Day of Year

Of course you could use caljd to determine the julian day of January 1 and subtract that from the current julian day. That ought to work.


Pete

Pete
Pat Lieberg
Valued Contributor
Solution

Re: Three-Digit Day of Year

I whipped this up quick. Its a script that asks for the month and day and then tdells you the day of the year it is. Note that it does not calculate leap year, so Feb was hard-coded to 28 days. That could be programmed in though.


#!/bin/ksh
#
print - n "Enter the month and day: "
read month day

set -A days 31 28 31 30 31 30 31 31 30 31 30 31
((n = 0))
((j_days = 0))

((month = month - 1))

while ((n < $month))
do
((j_days = j_days + ${days[$n]}))
((n = n + 1))
done

((j_days = j_days + $day))
echo $j_days
Pat Lieberg
Valued Contributor

Re: Three-Digit Day of Year

I forgot your desired result was inthe format dddyy, but you can add this to the end of the script:

year=$(date +%y)
result="$j_days$year"
echo $result


Hein van den Heuvel
Honored Contributor

Re: Three-Digit Day of Year



In Perl:

---- julian.p ----
use Time::Local;
($y,$m,$d) = unpack "a4 a2 a2", shift @ARGV;
$s1 = timelocal(0,0,1,$d,$m-1,$y-1900);
$s2 = timelocal(0,0,0,1,0,$y-1900);
$u = 1 + ($s1 - $s2)/86400;
printf "%02d%03d\n", $y-2000, $u;


I used the $U = 1 + ... because jan-1 is day 1.
I used the hour 1 in $s1 to deal with integer truncation.


Hein.
James R. Ferguson
Acclaimed Contributor

Re: Three-Digit Day of Year

Hi Michael:

A small perl script would easily help:

You an embed this in your shell and pass the Month Day Year as agruments. I've let it output a three-digit year and a three-digit day of year. THus 1999 outputs as 099 while 2005 appears as 105.

perl -e 'use Time::Local;$time=timelocal(0,0,0,$ARGV[1],$ARGV[0]-1,$ARGV[2]);($y,$d)=(localtime($time))[5,7];$d++;printf "%03d%03d\n"' 8 31 2005

...returns 105243

Obviously, you can use this in your shell like this:

RESULT=`perl -e `...`` $M $D $Y

Regards!

...JRF...
Hein van den Heuvel
Honored Contributor

Re: Three-Digit Day of Year


Ah yes, I forgot about the $yday = 8th field in the localtime result. Using that my script could change to:

---- cat julian.p -----
use Time::Local;
($y,$m,$d) = unpack "a4 a2 a2", shift @ARGV;
$u = 1 + (localtime(timelocal(0,0,1,$d,$m-1,$y-1900)))[7];
printf "%02d%03d\n", $y-2000, $u;


There is a minor typo / cut&paste error in the JRF solution.
Try this:


# perl -e 'use Time::Local;$time=timelocal(0,0,0,$ARGV[1],$ARGV[0]-1,$ARGV[2]);($y,$d)=(localtime($time))[5,7];$d++;printf "%03d%03d\n", $y,$d' 8 31 2005

105243
James R. Ferguson
Acclaimed Contributor

Re: Three-Digit Day of Year

Hi (again):

Yes, Hein, thank you. The paste I did cut off part of the script:

#!/usr/bin/perl
use Time::Local;
$time=timelocal(0,0,0,$ARGV[1],$ARGV[0]-1,$ARGV[2]);
($y,$d) = (localtime($time)) [5,7];
$d++;
printf "%03d%03d\n",$y,$d;

I like your use of 'unpack'. It would allow Michael to pass one argument to the perl script instead of three if that suits his needs better. Thanks for the correction to mine!

Regards!

...JRF...