hda has asked for the wisdom of the Perl Monks concerning the following question:

Wise monks, which is the best module/way for obtaining YYYYMMDD (year, month, day) from YYYYDOY (year, day of year)? I have used DateTime a lot to do the opposite, i.e. getting DOY from MMDD, but I can't figure out this one. Thanks in advance.
  • Comment on Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?

Replies are listed 'Best First'.
Re: Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?
by Corion (Patriarch) on Oct 01, 2008 at 09:54 UTC

    Inspired by moritz' use: Why not use DateTime for that as well?

    my $dt = DateTime->new( year => $yyyy, month => 1, day => 1 ); $dt->add( days => $doy ); print $dt->strftime( '%Y%m%d' );

      I prefer Date::Calc over DateTime because Date::Calc is very very fast and has almost no dependencies, where DateTime has a lot (and also does a lot more that I never need).

      update: the second pair of links show the dependencies in cpandeps

      For scripts, DateTime is ok, as it documents what you do in it's over-designed OO interface (I don't like OO if it isn't needed), but for one-liners and fast code, Date::Calc is my preferred module.

      Corion, your code fragment misses a  - 1:

      $ perl -MDateTime -le'my($y,$doy)=(2008,1);my$dt=DateTime->new(year=>$ +y,month=>1,day=>1);$dt->add(days=>$doy);print$dt->strftime("%Y%m%d")' 20080102 $ perl -MDateTime -le'my($y,$doy)=(2008,1);my$dt=DateTime->new(year=>$ +y,month=>1,day=>1);$dt->add(days=>$doy-1);print$dt->strftime("%Y%m%d" +)' 20080101 $ perl -MDate::Calc=Add_Delta_Days -e'my($y,$doy)=(2008,1);printf"%4d% +02d%02d\n",Add_Delta_Days($y,1,1,$doy-1)' 20080101

      Enjoy, Have FUN! H.Merijn
Re: Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?
by JavaFan (Canon) on Oct 01, 2008 at 09:50 UTC
    I'd use Date::Calc:
    use Date::Calc 'Add_Delta_Days'; my $yyyy_doy = "YYYYDOY"; my ($year, $doy) = $yyyy_doy =~ /(....)(...)/; my ($YYYY, $MM, $DD) = Add_Delta_Days ($year, 1, 1, $doy - 1);
    What you want is DOY - 1 days after January 1 of the given year.

    No doubt countless other modules on CPAN can do the same thing. But I like Date::Calc and that usually does what I need.

      I'll second Date::Calc - been using it for a few years and has generally done what I need.

Re: Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?
by moritz (Cardinal) on Oct 01, 2008 at 09:50 UTC
    With my favourite date module, Date::Simple:
    use strict; use warnings; use Date::Simple qw(date); my ($year, $day_of_year) = (2008, 127); my $d = date("$year-01-01") + $day_of_year - 1; print $d, "\n"; __END__ 2008-05-06
Re: Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?
by duelafn (Parson) on Oct 01, 2008 at 10:09 UTC

    From DateTime docs:

    • from_day_of_year( ... )
      This constructor takes the same arguments as can be given to the "new()" method, except that it does not accept a "month" or "day" argument. Instead, it requires both "year" and "day_of_year". The day of year must be between 1 and 366, and 366 is only allowed for leap years.

    Good Day,
        Dean

Re: Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?
by andreas1234567 (Vicar) on Oct 01, 2008 at 10:29 UTC
    With Date::Manip:
    $ cat 714749.pl use strict; use warnings; use Date::Manip; # YYYYDOY -> YYYYMMDD while (<DATA>) { m/(\d{4})(\d{3})/; my ($y,$m,$d,$h,$mn,$s) = Date_NthDayOfYear($1,$2); printf("%04d-%02d-%02d\n", $y, $m, $d); } __DATA__ 2008001 2008002 2008003 2008004 2008005 2008360 2008361 2008362 2008363 2008364 2008365 2008366
    $ perl 714749.pl 2008-01-01 2008-01-02 2008-01-03 2008-01-04 2008-01-05 2008-12-25 2008-12-26 2008-12-27 2008-12-28 2008-12-29 2008-12-30 2008-12-31
    --
    No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]
Re: Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?
by Anonymous Monk on Oct 01, 2008 at 10:02 UTC
    DateTime::Format::Strptime
    #!/usr/bin/perl -- use strict; use warnings; use DateTime::Format::Strptime; my( @strp ) = ( DateTime::Format::Strptime->new( pattern => '%Y%m%d', ), DateTime::Format::Strptime->new( pattern => '%Y%j', ) ); for my $yyyymmdd ( qw[ 20050526 20040401 20060201 ]){ my $yyyydoy = $strp[0]->parse_datetime($yyyymmdd); print "$yyyymmdd # $yyyydoy # ", $strp[1]->format_datetime($yyyydo +y),$/; } __END__ 20050526 # 2005-05-26T00:00:00 # 2005146 20040401 # 2004-04-01T00:00:00 # 200492 20060201 # 2006-02-01T00:00:00 # 200632
Re: Best way of getting YEAR-MONTH-DAY from YEAR-DAYOFYEAR ?
by hda (Chaplain) on Oct 01, 2008 at 10:02 UTC
    Hey cool! Adopted the DateTime solution, since I am already using that module in the program. Thanks everyone for the prompt and kind help!