[R] year and week to date - before 1/1 and after 12/31

Jeff Newmiller jdnewm|| @end|ng |rom dcn@d@v|@@c@@u@
Thu Oct 18 05:19:01 CEST 2018


You cannot obtain a predictable result by sending invalid time 
representation data to strptime... you have to work with valid time 
representations.
See sample approach below:

############################
weekEnds <- function( DF ) {
    d1_1 <- as.Date( sprintf( "%04d 1 1"
                            , DF[[ "Y" ]]
                            )
                   , format = "%Y %U %u"
                   )
    d52_7 <- as.Date( sprintf( "%04d 52 7"
                             , DF[[ "Y" ]]
                             )
                    , format = "%Y %U %u"
                    )
    week <- as.difftime( 7, units = "days" )
    day <- as.difftime( 1, units = "days" )
    d <- as.Date( sprintf( "%04d %d 1"
                         , DF[[ "Y" ]]
                         , DF[[ "wn" ]]
                         )
                , format = "%Y %U %u"
                )
    before <- 0 == DF[[ "wn" ]]
    after <- 53 == DF[[ "wn" ]]
    d[ before ] <- d1_1[ before ] - week
    d[ after ] <- d52_7[ after ] + day
    DF[[ "weekBegin" ]] <- d
    DF[[ "weekEnd" ]] <- d + week
    DF
}

tst <- expand.grid( Y = 2000:2028
                   , wn = c( 0, 1, 53 )
                   )

result <- weekEnds( tst )
set.seed( 42 )
result[ sample( nrow( result ), 5 ), ]
#>       Y wn  weekBegin    weekEnd
#> 80 2021 53 2021-12-27 2022-01-03
#> 81 2022 53 2022-12-26 2023-01-02
#> 25 2024  0 2024-01-01 2024-01-08
#> 70 2011 53 2011-12-26 2012-01-02
#> 54 2024  1 2024-01-08 2024-01-15
sum( is.na( result$weekBegin ) )
#> [1] 0
############################

On Tue, 16 Oct 2018, peter salzman wrote:

> hi,
> thanks for replying,
> 
> it has taken some time to understand
> 
> i have year+week and i need to find the 1st day and the last day of that week
> i can decide when week starts
> 
> for example these 3 examples:
> df <- data.frame(id = 1:3, year = c(2018, 2018, 2018), week=c(0,1,52))
> 
> ## now run for all 3 rows:
> for (kk in 1:3) {
>   print(df[kk,])
>   print('## version 1')
>   print(as.Date(paste(df$year[kk],df$week[kk],'Sun',sep=' '), format = "%Y %U %a")       ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'Mon',sep=' '), format = "%Y %U %a")       ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'Tue',sep=' '), format = "%Y %U %a")       ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'Wed',sep=' '), format = "%Y %U %a")       ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'Thu',sep=' '), format = "%Y %U %a")       ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'Fri',sep=' '), format = "%Y %U %a")       ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'Sat',sep=' '), format = "%Y %U %a")       )
>   
>   print('## version 2')
>   print(as.Date(paste(df$year[kk],df$week[kk],'7',sep=' '), format = "%Y %U %u")        ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'1',sep=' '), format = "%Y %U %u")         ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'2',sep=' '), format = "%Y %U %u")         ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'3',sep=' '), format = "%Y %U %u")         ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'4',sep=' '), format = "%Y %U %u")         ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'5',sep=' '), format = "%Y %U %u")         ) 
>   print(as.Date(paste(df$year[kk],df$week[kk],'6',sep=' '), format = "%Y %U %u")         )
> }
> 
> for week 0 we get NA for Sunday because it was Dec 31, 2017
> similarly for week 52 we get NA for Tue,Wed, ... because these are in January of 2019
> 
> my hope was to write 
> as.Date(paste(year,week,1), format "%Y %month %weekday")
> as.Date(paste(year,week,7), format "%Y %month %weekday")
> and get the first and last day of the given week even at the beginning and end of year
> for example
> as.Date("2018 0 Sun","%Y %U %a")   = '2017-12-31'
> 
> i hope this makes sense.
> 
> thanks for replying
> peter
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> On Tue, Oct 16, 2018 at 2:11 PM Jeff Newmiller <jdnewmil using dcn.davis.ca.us> wrote:
>       Er, my mistake, you are using %U not %W... but now I am really confused, because the first Sunday is trivial with %U/%u.
>
>       Can you clarify what your actual upstream input is? Is it an invalid date string as you say below, or is it year number?
>
>       On October 16, 2018 10:22:10 AM PDT, Jeff Newmiller <jdnewmil using dcn.davis.ca.us> wrote:
>       >If the date in your character representation does not exist then there
>       >is no requirement for a POSIX function to give any reliable answer...
>       >including NA. Using 00 as the week number won't always work.
>       >
>       >The first week/weekday combination that is guaranteed to exist by POSIX
>       >is 1/1 (first Monday). If the corresponding mon/mday is 1/1 then no
>       >days exist in week zero for that year and the first Sunday is 6 days
>       >more than the mday of the first Monday, else the mday of the first
>       >Sunday is one day less than the mday of the first Monday.
>       >
>       >You should if at all possible repair the computations that are creating
>       >the invalid string dates you mention.
>       >
>       >On October 16, 2018 8:11:12 AM PDT, peter salzman
>       ><peter.salzmanuser using gmail.com> wrote:
>       >>it is simpler than i thought
>       >>
>       >>first day of given week is the last day minus 6days
>       >>
>       >>in other words:
>       >>d1 = as.Date('2018 00 Sat',format="%Y %U %a") - 6
>       >>d2 = as.Date('2018 00 Sun',format="%Y %U %a")
>       >>are the same as long both are not NA
>       >>
>       >>therefore to get the one that is not NA one can do
>       >>
>       >>max( c(d1,d2), na.rm=TRUE )
>       >>
>       >>maybe there is some other trick
>       >>
>       >>best,
>       >>peter
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>On Tue, Oct 16, 2018 at 10:22 AM peter salzman
>       >><peter.salzmanuser using gmail.com>
>       >>wrote:
>       >>
>       >>> hi,
>       >>>
>       >>> to turn year and week into the date one can do the following:
>       >>>
>       >>> as.Date('2018 05 Sun', "%Y %W %a")
>       >>>
>       >>> however, when we want the Sunday (1st day of week) of the 1st week
>       >of
>       >>2018
>       >>> we get NA because 1/1/2018 was on Monday
>       >>>
>       >>> as.Date('2018 00 Mon',format="%Y %U %a")
>       >>> ## 2018-01-01
>       >>> as.Date('2018 00 Sun',format="%Y %U %a")
>       >>> ## NA
>       >>>
>       >>> btw the same goes for last week
>       >>> as.Date('2017 53 Sun',format="%Y %U %a")
>       >>> ## 2017-12-31
>       >>> as.Date('2017 53 Mon',format="%Y %U %a")
>       >>> ## NA
>       >>>
>       >>> So my question is :
>       >>> how do i get
>       >>> from "2018 00 Sun" to 2018-12-31
>       >>> and
>       >>> from "2017 53 Mon" to 2018-01-01
>       >>>
>       >>> i realize i can loop over days of week and do some if/then
>       >>statements,
>       >>> but is there a built in function?
>       >>>
>       >>> thank you
>       >>> peter
>       >>>
>       >>>
>       >>>
>       >>>
>       >>>
>       >>> --
>       >>> Peter Salzman, PhD
>       >>> Department of Biostatistics and Computational Biology
>       >>> University of Rochester
>       >>>
>
>       --
>       Sent from my phone. Please excuse my brevity.
> 
> 
> 
> --
> Peter Salzman, PhD
> BMS
> Greater Boston Area, MA
> 
>

---------------------------------------------------------------------------
Jeff Newmiller                        The     .....       .....  Go Live...
DCN:<jdnewmil using dcn.davis.ca.us>        Basics: ##.#.       ##.#.  Live Go...
                                       Live:   OO#.. Dead: OO#..  Playing
Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
/Software/Embedded Controllers)               .OO#.       .OO#.  rocks...1k
---------------------------------------------------------------------------


More information about the R-help mailing list