Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I use the date command to convert something like "monday week 40" into a ISO date?

I am playing with something like this:

date --date='monday week 40' +'%Y-%m-%d'

And the date I'm searching for would be 2011-10-03.

But my problem is that this date string is not valid, so I need another approach to solve this problem.

/Thanks

share|improve this question
    
The following link is about what determines on which day of the year a numbered week begins. Week numbering (Wikipedia).. It effectively explains why the 1st of Janunuary of this year is in ISO week 52 .. The %V format sequence used by 'user unknown' reports the ISO week number. –  Peter.O Sep 1 '11 at 16:16

3 Answers 3

up vote 3 down vote accepted

Really ugly and probably works only with GNU date:

date -d "$( date -d "$( date +'%Y-01-01' ) +40 weeks") -$( date -d "$( date +'%Y-01-01' ) +40 weeks" +'%w' ) days+1 day" +'%Y-%m-%d'

Tested only for your 3 October example, may fail for some other cases.


Update: If you have a non eng locale you need to specify the output from the inner date to get to to work. (And %F just is YYYY-MM-DD).

date -d "$(date -d "$(date +'%Y-01-01') +40 weeks" +"%F") -$(date -d "$(date +'%Y-01-01') +40 weeks" +%w) days +1 day" +"%F"
share|improve this answer
1  
You missed to format the output from the inner date so the outer could use it correctly. –  Johan Sep 1 '11 at 11:19
    
@Johan, I had no problem with using the default format. Maybe it is locale specific? I use en_US. Good point anyway. –  manatwork Sep 1 '11 at 11:34
    
For the date I use the Swedish locale, so there is the difference. –  Johan Sep 1 '11 at 13:09
    
Thanks for the locale adjustment. I have a custom date format and had the same problem.. I had almost sorted it out, but now you've posted it I'll use your tweak; it's better. –  Peter.O Sep 1 '11 at 14:32
    
There was no requirement for this to be a one-liner. It would be better to split this into multiple lines, using temporary variables with descriptive names to make it clear how it works. It also assumes that Jan 1st is in the same week number each year, which is not the case as already noted by @Peter.O. –  Adam Spiers Sep 2 '13 at 11:16

An alternative approach:

date --date "+$((40-$(date +%V)))weeks last monday"  +"%F"
  • 40 is the week you search for
  • date +%V returns the current week (35)
  • 40-35 = 5, which is the number of weeks to add
  • from there, seek the last monday
share|improve this answer
    
good one, and it works with my custom date setting. –  Peter.O Sep 1 '11 at 14:31
    
This is a clever idea, but it doesn't work. For example, if today is Monday in week 41 (i.e. date +%V returns 41), then the --date parameter value will be +-1weeks last monday, which is actually a fortnight ago, not 7 days ago. –  Adam Spiers Sep 2 '13 at 11:09
    
I'm not sure whether I understand your critique. It's 2013 this year, so the example from the question doesn't fit. What should be the absolute date for the question, and what does my approach return instead (maybe: why)? –  user unknown Sep 2 '13 at 22:32
    
@AdamSpiers: My calendar displays as Monday, week 40 the 30th of Sep. which is what my algo yields (today). –  user unknown Sep 2 '13 at 22:38
    
@userunknown That's because you are testing your code today, which is a Tuesday, which comes after Monday. If you had tested your code yesterday, it would have broke. To make it more obvious, try running date -d 'last monday'. It will return yesterday. What do you think it would have said if you had run it yesterday? –  Adam Spiers Sep 3 '13 at 13:38

OK, here's my attempt. It steals ideas from the other answers, and attempts to make the logic easier to follow. This is based on the ISO 8601 system, so it won't be correct if you live in countries such as USA or Canada, but should be easily adjustable for those countries.

# sets $week_start to a representation of Monday of the given week
# number formatted via the given format, and similarly sets
# $week_end to Friday of the same week.
get_week_range () {
    week_num="$1" date_format="$2"

    # Most of the world adhere to ISO 8601 which states that weeks begin on Monday
    # and Jan 4th is always in week #1:
    #
    #   http://en.wikipedia.org/wiki/ISO_week_date
    #
    # For other week numbering systems (e.g. USA, Canada), see:
    #
    #   http://en.wikipedia.org/wiki/Seven-day_week#Week_numbering
    day_in_week_1=$( date +'%Y-01-04' )
    day_num_in_week_1=$( date -d $day_in_week_1 +%u ) # 1 is Monday
    days_from_week_1_start=$(( $day_num_in_week_1 - 1 ))
    # This is a Monday:
    start_of_week_1=$( date -d "$day_in_week_1 - $days_from_week_1_start days" +%F )

    week_delta="$(( $week_num - 1 ))"
    # Monday:
    week_start=$( date -d "$start_of_week_1 + $week_delta weeks"          +"$date_format" )
    # Friday:
    week_end=$(   date -d "$start_of_week_1 + $week_delta weeks + 4 days" +"$date_format" )
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.