# Fwd: DayRange(#92) - My solution

**URL:** <https://www.ruby-forum.com/t/fwd-dayrange-92-my-solution/67026>\
**Category:** Ruby\
**Created:** [August 31, 2006, 12:40am UTC](https://www.ruby-forum.com/t/fwd-dayrange-92-my-solution/67026 "2006-08-31T00:40:28Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![rykkers](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/e5b9ba/32.png) [@rykkers](https://www.ruby-forum.com/u/rykkers)\
**Post date:** [August 31, 2006, 12:40am UTC](https://www.ruby-forum.com/t/fwd-dayrange-92-my-solution/67026/1 "2006-08-31T00:40:28Z")

</div>

Brian pointed out that I’d missed the spec and was hypenating two day  
runs instead of the minimum run called for.

So, I’ve updated my solution to fix this, and keeping with the spirit  
of options, I added a :min\_span option to set the minimum number of  
days to coalesce.

I’ve also made to\_s work with the :week\_start option as well.

I was going to go ahead and add the ability to specify the :week\_start  
as a string as well as an integer, but I realized that I really need  
to refactor a bit before I do that, so I stopped for now.

---------- Forwarded message ----------  
From: Bryan D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Date: Aug 30, 2006 2:45 PM  
Subject: Re: [QUIZ] DayRange(#92) - My solution  
To: removed\_email\_address@domain.invalid

Rick,

Wow, a very detailed and extensive solution…

I did notice one thing, and maybe this was intentional, but when you  
pass in 1,2,4,5 you should get “Mon, Tue, Thu, Fri”, not “Mon-Tue,  
Thu-Fri”. However, this is just according to the quiz “rules” and is  
not necessarily the best way. Maybe an option to specify the minimum  
number of consecutive days to constitute a “range” would be a good  
addition. I’ll probably add that to my own version …

Regards,  
Bryan

On 8/30/06, Rick DeNatale [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> lots of new features. I guess I fall into the latter camp.  
> will never span over a week boundary.
> 
> –  
> Rick DeNatale
> 
> My blog on Ruby  
> [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

IPMS/USA Region 12 Coordinator  
[http://ipmsr12.denhaven2.com/](http://ipmsr12.denhaven2.com/)

Visit the Project Mercury Wiki Site  
[http://www.mercuryspacecraft.com/](http://www.mercuryspacecraft.com/)

---

<div class="post-metadata">

**Author:** ![rykkers](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/e5b9ba/32.png) [@rykkers](https://www.ruby-forum.com/u/rykkers)\
**Post date:** [August 31, 2006, 1:40am UTC](https://www.ruby-forum.com/t/fwd-dayrange-92-my-solution/67026/2 "2006-08-31T01:40:36Z")

</div>

Ackkkk!

I just noticed how my attachments came over on the rubyquiz website.  
So here’s the code in-line in the message  
=== subranges.rb ===  
module Enumerable

```
# Return an array containing the sub-ranges of sorted contents of the 

```

receiver  
# Each element must be comparable, and must respond to succ  
def subranges(min\_span = 2)  
range\_start = range\_end = nil  
subranges = []  
self.sort.each do |elem|  
if range\_start.nil?  
range\_start = range\_end = elem  
else  
if range\_end.succ == elem  
range\_end = elem  
else  
subrange = (range\_start…range\_end)  
if subrange.entries.length \>= min\_span  
subranges \<\< subrange  
else  
subrange.each {|ea| subranges \<\< (ea…ea) }  
end  
range\_start = range\_end = elem  
end  
end  
end  
unless range\_start.nil?  
subrange = (range\_start…range\_end)  
if subrange.entries.length \>= min\_span  
subranges \<\< subrange  
else  
subrange.each {|ea| subranges \<\< (ea…ea)}  
end  
end  
subranges  
end

end

=== test\_day\_range.rb===  
require ‘day\_range.rb’  
require ‘test/unit’

class TestDayRange \< Test::Unit::TestCase

```
EsperantoMap = {"Lundo" => 1, "Lun" => 1, "Mardo" => 2, "Mar" => 2,

```

“Merkredo” =\> 3, “Mer” =\> 3,  
“Jhaudo” =\> 4, “Jha” =\> 4, “Vendredo” =\> 5, “Ven” =\> 5, “Sabato” =\>  
6, “Sab” =\> 6,  
“Dimancho” =\> 7, “Dim” =\> 7}

```
EsperantoNames = ["Lun", "Mar", "Mer", "Jha", "Ven", "Sab","Dim"]

GermanMap = { "Montag" => 1, "Mon" => 1, "Dienstag" => 2, "Die" => 2,

```

“Mittwoch” =\> 3, “Mitt” =\> 3,  
“Donnerstag” =\> 4, “Don” =\> 4, “Freitag” =\> 5, “Frei” =\> 5,  
“Samstag” =\> 6, “Sam” =\> 6,  
“Sonntag” =\> 7, “Sonn” =\> 7 }  
GermanNames = [“Mon”, “Die”, “Mitt”, “Don”, “Frei”, “Sam”, “Sonn”]

```
def test_equal_1
	dr1 = DayRange.new(1,2,4,5)
	dr2 = DayRange.new(1,2,4,5)
	dr3 = DayRange.new(2,5,4,1)
	assert_equal(dr1,dr2)
	assert_equal(dr1,dr3)
end

def test_weekstart_1
	dr1 = DayRange.new('Mon', 'Tuesday', 'Thursday', 'Friday', 'Sat',

```

:week\_start =\> 2)  
assert\_equal(“Tue, Thu-Sat, Mon”,dr1.to\_s)  
end

```
def test_equal_2
	dr1 = DayRange.new(1,2,4,5)
	dr2 = DayRange.new('Monday', 'Tuesday', 'Thursday', 'Friday')
	assert_equal(dr1,dr2)
end

def test_to_s_numbers
	dr = DayRange.new(1,2,4,5)
	assert_equal("Mon-Tue, Thu-Fri",dr.to_s(:min_span => 2))
	assert_equal("Mon, Tue, Thu, Fri",dr.to_s)
	dr = DayRange.new(1,2,3, 5,6)
	assert_equal("Mon-Wed, Fri-Sat",dr.to_s(:min_span => 2))
	assert_equal("Mon-Wed, Fri, Sat",dr.to_s)
end

def test_to_s_names
	dr = DayRange.new('Monday', 'Tuesday', 'Thursday', 'Friday')
	assert_equal("Mon, Tue, Thu, Fri",dr.to_s)
	assert_equal("Mon-Tue, Thu-Fri",dr.to_s(:min_span => 2))
end

def test_to_s_options
	dr = DayRange.new('Monday', 'Tuesday', 'Thursday', 'Friday')
	assert_equal("Lun, Mar, Jeu, Ven", dr.to_s(:language => :French))
	assert_equal("Lun-Mar, Jeu-Ven", dr.to_s(:language => :French,

```

:min\_span =\> 2))  
assert\_equal(“Mercury-Venus, Mars-Saturn”,  
dr.to\_s(:day\_names =\> %w[Mercury Venus Earth Mars Saturn  
Jupiter Uranus],  
:min\_span =\> 2)  
)

```
        dr = DayRange.new(1, 2, 3, 6, 7)
	assert_equal("Mon-Wed, Sat, Sun", dr.to_s)
	assert_equal("Tue, Wed, Sat-Mon", dr.to_s(:week_start => 2))
	assert_equal("Wed, Sat-Tue",dr.to_s(:week_start => 3))
	assert_equal("Sat-Wed", dr.to_s(:week_start => 4))
	assert_equal("Sat-Wed", dr.to_s(:week_start => 5))
	assert_equal("Sat-Wed", dr.to_s(:week_start => 6))
	assert_equal("Sun-Wed, Sat", dr.to_s(:week_start => 7))
end
def test_translate_to_french
	dr = DayRange.new(1,2,4,5)
	assert_equal("Lun, Mar, Jeu, Ven",dr.to_s(:language => 'French'))
	assert_equal("Lun-Mar, Jeu-Ven",dr.to_s(:language => 'French',

```

:min\_span =\> 2))  
end

```
def test_new_french
	dr1F = DayRange.new(1,2,4,5, :language => 'French')
	dr1 = DayRange.new(1,2,4,5)
	assert_equal(dr1, dr1F)
	assert_equal("Lun-Mar, Jeu-Ven",dr1F.to_s(:min_span => 2))
	assert_equal("Mon-Tue, Thu-Fri",dr1F.to_s(:language => 'English',

```

:min\_span =\> 2))  
assert\_equal(“Lun, Mar, Jeu, Ven”,dr1F.to\_s)  
assert\_equal(“Mon, Tue, Thu, Fri”,dr1F.to\_s(:language =\> ‘English’))  
end

```
def test_new_esperanto
	dr1Esp = DayRange.new(1,2,4,5, :day_map => EsperantoMap)
	dr1 = DayRange.new(1,2,4,5)
	assert_equal(dr1, dr1Esp)
	assert_equal("Lun-Mar, Jha-Ven", dr1Esp.to_s(:min_span => 2))
end

def test_bad_days
	assert_raise(ArgumentError) {DayRange.new(1,2,8)}
	assert_raise(ArgumentError) {DayRange.new(1, :day_map => {'Mon' =>

```

1, “Tue” =\> 9})}  
end

```
def test_add_german
	DayRange.remove_language(:German)
	DayRange.add_language(:German, GermanMap, GermanNames)
	assert_equal("Die, Don, Sam, Sonn", DayRange.new(2,4,6,7, :language

```

=\> ‘German’).to\_s)  
assert\_equal(“Die, Don, Sam-Sonn”, DayRange.new(2,4,6,7,  
:language =\> ‘German’).to\_s(:min\_span =\> 2))

```
	DayRange.remove_language(:German)
	DayRange.add_language(:German, GermanMap)
	assert_equal("Die, Don, Sam, Sonn", DayRange.new(2,4,6,7, :language

```

=\> ‘German’).to\_s)  
assert\_equal(“Die, Don, Sam-Sonn”, DayRange.new(2,4,6,7,  
:language =\> ‘German’).to\_s(:min\_span =\> 2))  
end

```
def test_each_name
	dr = DayRange.new(1,2, 5, 6)
	expected = ['Mon', 'Tue', 'Fri', 'Sat']
	dr.each_name { |name| assert_equal(expected.shift, name)}
	assert(expected.empty?, "Missing results #{expected.inspect}")
	expected = ['Doc', 'Grumpy', 'Bashful', 'Sleepy']
	dwarves = ['Doc', 'Grumpy', 'Happy', 'Sneezy','Bashful', 'Sleepy', 

```

‘Dopey’]  
dr.each\_name(:day\_names =\> dwarves) { |name|  
assert\_equal(expected.shift, name)}  
assert(expected.empty?, “Missing results #{expected.inspect}”)  
expected = [‘Lun’, ‘Mar’, ‘Ven’, ‘Sam’]  
dr.each\_name(:language =\> ‘French’) { |name|  
assert\_equal(expected.shift, name)}  
assert(expected.empty?, “Missing results #{expected.inspect}”)  
end  
end

=== day\_range.rb===

# This class was written as an answer to RubyQuiz92.

# 

# The DayRange.new method takes one or more day specifications as

either integers or natural language

# strings representing day names. An instance will respond to to\_s

with a string representing

# the list of days with consecutive days collapsed to a form like

‘Mon-Fri’

# 

# Several methods take “Rails-style” options, one or more associations

after any normal parameters.

# The keys of these associations can be Strings or symbols which will

be converted using to\_sym.

# 

# Features not called for in the quiz include:

# 

# \* A number for the start of the week may be specified. This will

affect the output of

# to\_s. For example, :week\_start =\> 7, indicates that the week

starts on Sunday, and

# DayRange.new(‘Sat’, ‘Sun’, ‘Mon’, :week\_start =\> 7).to\_s =\>

“Sun-Mon, Sat”

# 

# \* Support is provided for languages other than English, French is

built in, but additional

# languages can be added, either on the new call, or by a class

method DayRange.add\_language

# 

# \* DayRanges are enumerable and produce the numbers of the day they

contain, in Monday-Sunday

# order.

# 

# \* Two Dayranges are == if they contain the same days

# 

# Author: Rick DeNatale [http://talklikeaduck.denhaven2.com](http://talklikeaduck.denhaven2.com)

# 

# Test cases are in the file testdayrange.rb

# 

# The code which does most of the work in detecting sub-ranges is in

the file subranges.rb

# This adds a method to Enumerable which produces an array of ranges

which cover the same contents

# as the Enumeration.

require ‘subranges’

# 

class DayRange

```
include Enumerable

# StringSymHash extends Hash so that symbol and string keys are

```

equivalent a la Rails  
# Normally I don’t like implementing things like this via sub-classing  
but…  
class StringSymHash \< Hash

```
	def [](key)
		super(key.to_sym)
	end

	def []=(key,value)
		super(key.to_sym, value)
	end

	def StringSymHash.[](hash)
		ssh = StringSymHash.new
		hash.each { |k, v| ssh[k] = v}
		ssh
	end
end

# maps and names for English and French
@@day_maps = StringSymHash[ :English => {
                                         'Monday' => 1, 'Mon' =>

```

1, ‘Tuesday’ =\> 2, ‘Tue’ =\> 2,  
‘Wednesday’ =\> 3, ‘Wed’ =\> 3,  
‘Thursday’ =\> 4, ‘Thu’ =\> 4,  
‘Friday’ =\> 5, ‘Fri’ =\> 5, ‘Saturday’  
=\> 6, ‘Sat’ =\> 6,  
‘Sunday’ =\> 7, ‘Sun’ =\> 7 },  
:French =\> {  
‘Lundi’ =\> 1, ‘Lun’ =\> 1,  
‘Mardi’ =\> 2, ‘Mar’ =\> 2,  
‘Mercredi’ =\> 3, ‘Mer’ =\> 3, ‘Jeudi’ =\>  
4, ‘Jeu’ =\> 4,  
‘Vendredi’ =\> 5, ‘Ven’ =\> 5, ‘Samedi’  
=\> 6, ‘Sam’ =\> 6,  
‘Dimanche’ =\> 7, ‘Dim’ =\> 7 } ]  
@@day\_names = StringSymHash[  
:English =\> [nil, ‘Mon’, ‘Tue’, ‘Wed’, ‘Thu’, ‘Fri’, ‘Sat’, ‘Sun’],  
:French =\> [nil, ‘Lun’, ‘Mar’, ‘Mer’, ‘Jeu’, ‘Ven’, ‘Sam’, ‘Dim’],  
]

```
# Add a language to those supported by the DayRange class
#
# :call-seq:
# DayRange.add_language(lang_name, day_map[, day_names])
#
# The <em>lang_name_ parameter</em> is the name of the language. It

```

will be internally converted  
# to a symbol. So, for example, if you have:  
#  
# DayRange.add\_language(‘Esperanto’, …)  
#  
# then one could ask for a DayRange in Esperanto with:  
#  
# DayRange.new(1, 3, :Language =\> :Esperanto)  
#  
# The _day\_map_ parameter should be a Hash which maps day  
names to integers in  
# the range (1…7). More than one name may map to a particular  
day\_number.  
#  
# The _day\_names_ parameter must be duck-typeable to a 7-element  
array or Strings, with the  
# first element containing the name which will be used for Monday for  
output (e.g. for to\_s),  
# and the last for Sunday.  
#  
# If _day\_names_ is omitted, then it will be constructed by finding a  
name for each day\_number  
# as least as short as any other name which maps to that day\_number  
in _day\_map_  
def DayRange.add\_language(lang\_name, day\_map, day\_names = nil)  
#HACK - if user supplied day\_names pre-pend an element so that we can  
use  
# pseudo 1-origin indexing

```
	day_names = day_names.dup.unshift('') if day_names
	@@day_names[lang_name.to_s] = validated_day_names(day_names ||

```

day\_names\_from\_day\_map(day\_map))  
@@day\_maps[lang\_name.to\_s] = day\_map.dup  
end

```
# Remove the language _lang_name_
# Do nothing silently if _lang_name_ is not present
#
# :call-seq:
# DayRange.remove_language(lang_name)
#
def DayRange.remove_language(lang_name)
	@@day_names.delete(lang_name)
	@@day_maps.delete(lang_name)
end

def DayRange.day_names_from_day_map(day_map) #:nodoc:
	# set each days name to the shortest name
	# in the name mapping
	# puts("Debug- DayRange.day_names_from_day_map(#{day_map})")
	day_names = Array.new(8)
	day_map.each do |name ,number|
		current_name = day_names[number] || day_names[number] = name
		day_names[number] = name if name.length < current_name.length
	end
	validated_day_names(day_names)
end

def DayRange.validated_day_names(day_names) #:nodoc:
	(1..7).each do |i|
		check_arg(day_names[i], "No name for day number #{i}")
	end
	day_names
end

def DayRange.check_arg(assertion, msg) # :nodoc:
	raise ArgumentError.new( msg) unless assertion
end

def DayRange.day_names_from_options(options, day_map) # :nodoc:
	# puts "Debug- 

```

DayRange.day\_names\_from\_options(options=#{options.inspect},"  
# puts " day\_map=#{day\_map.inspect})"  
return options[:day\_names] if options.key?(:day\_names)  
return DayRange.day\_names\_from\_day\_map(day\_map)  
end

```
def DayRange.language_from_options(options) # :nodoc:
	get_option(:language, options, :English)
end

def DayRange.get_option(option, options, default) # :nodoc:
	options.key?(option) ? options[option] : default
end

# Returns a new DayRange (which contains one or more days of the week)
#
# :call-seq:
# DayRange.new(day* [, options])
#
# <em>day</em> arguments can be either numbers in the range
# (1..7) or names in the <em>day_mapping</em> (see <b>:day_mapping</b> 

```

option).  
#  
# Options:  
#  
# [_:language_ =\> symbol] Specifies the language to be used to  
# interpret the \_day\_s which are Strings, and for the default options  
for output via DayName#to\_s  
# The possible values for the symbol are :English, and :French,  
# additional languages can be added via the DayRange.addLanguage  
# method. If this option is not specified, :English will be used.  
#  
# [_:day\_\_map_ =\> hash] The value _hash_ should be a hash which maps  
the names  
# of days to the number of the day, with 1 being the first  
# day of the week (normally Monday), up to 7 for the last day  
# of the week (normally Sunday).  
# More than one name may map to the same day. If not specified,  
# the day\_mapping for the selected language is used.  
#  
# [_:day\_names_ =\> array] The value _array_ must be duck-typeable to  
a 7-element array.  
# The elements are the names of the days to be used by default for  
# output (e.g. with DayRange#to\_s. If not specified, then the  
day\_names for the selected  
# language will be used, unless _:day\_map_ is specified in which case  
# _:day\_names_ will be computed from one of the sortest names in the  
map for each  
# day.  
#  
# [_:week\_start_ =\> int] The value _int_ must be in the range (1, 7).  
# It is used to shift the start of the week. For example to create a  
# DayRange for a week which starts on Sunday rather than Monday,  
# specify a week\_start of 7. Although it is also possible to  
# achieve the same effect by changing the numbers in day\_mapping,  
# using week\_start allows the same day\_mapping to be used for weeks  
# starting on different days.  
#  
# [_:min\_span_ =\> int] The value _int_ indicates the minimum span of  
days which will  
# be collapsed into hyphenated form. The default is 3, as specified  
by the Quiz spec  
# I missed this the first time.  
def initialize( \*days ) #:doc:  
options = extract\_options\_from\_args!(days)  
# puts “Debug: options = #{options.inspect}”  
@day\_map = day\_map\_from\_options(options)  
@day\_map.each do |name, number|  
DayRange.check\_arg((1…7) === number,  
“‘#{number}’ is not an  
acceptable day for #{name.to\_s}.”)  
end  
@min\_span = DayRange.get\_option(:min\_span, options, 3)  
@language = DayRange.language\_from\_options(options)  
@day\_names = DayRange.day\_names\_from\_options(options,@day\_map)  
@week\_start = week\_start\_from\_options(options, @day\_map)  
@day\_numbers = days.map do | day |  
number = @day\_map[day] || day  
DayRange.check\_arg((1…7) === number, “‘#{number.inspect}’ is not  
an acceptable day.”)  
number  
end  
@day\_numbers.sort!  
end

```
# Return an array of subranges of @day_numbers adjusted for the 

```

week\_start  
def adjusted\_ranges(min\_span, week\_start)  
(week\_start == 1 ? @day\_numbers : @day\_numbers.map { |elem|  
ws\_adj(elem,week\_start) }).subranges(min\_span)  
end

```
# Two DayRanges are == if they contain the same day numbers
def ==(other)
	false unless other.kind_of? DayRange
	self.to_a == other.to_a
end

# Call _block_ once for each day number in _day_range_ passing the

```

day number to the block.  
# The order should be the same regardless of week start, i.e. Monday  
should always come first  
# then Tuesday, etc.  
#  
# :call-seq:  
# day\_range.each {|day\_number| block } → _day\_range_  
def each()  
@day\_numbers.each { | elem | yield elem }  
end

```
# Convert _day_range_ to an array, elements will be in order so that

```

Monday, if it is the range  
# will be first then Tuesday, etc. i.e. the effect of weekstart will  
be removed  
# :call-seq:  
# day\_range.to\_a  
def to\_a  
@day\_numbers.dup  
end

```
# Call _block_ once for each day name in _day_range_, passing that

```

name to the block  
#  
# :call-seq:  
# day\_range.each\_name [(options)] { |day\_name| block } →   
_day\_range_  
#  
# _Options_  
#  
# Options are specified Rails style, as one or more associations at  
the end of the argument  
# list.  
#  
# [_:language_ =\> symbol] Specifies the language to be used for the  
names  
# The possible values for the _symbol_ are :English, and :French,  
# additional languages can be added via the DayRange.addLanguage  
# method. If this option is not specified, :English will be used.  
#  
# [_:day\_names_ =\> array] The _array_ must be 7-element array.  
# The elements are the names of the days to be used by default for  
# output via to\_s. If not specified, then the day\_name for the  
selected  
# language will be used.  
#  
def each\_name(options={})  
names = get\_names\_override(options)  
to\_a.each { | day\_number | yield names[day\_number] }  
end

```
def get_names_override(options)
	return options[:day_names].dup.unshift('') if options.key?(:day_names)
	language = options[:language]
	return @@day_names[language] if language
	@day_names
end

# Returns a string representing the DayRange, Options can be specified.
#
# :call-seq:
# day_range.to_s [(options)]
#
# Options:
#
# [*:language* => symbol] Specifies the language to be used for output
# The possible values for _symbol_ are :English, and :French,
# additional languages can be added via the DayRange.addLanguage
# method. If this option is not specified, the language used when the 

```

DayRange  
# was created will be used.  
#  
# [_:day\_names_ =\> array] The _array_ must be duck-typeable to a  
7-element array.  
# The elements are the names of the days to be used by default for  
# output via to\_s. If not specified, then the day\_names for the  
selected  
# language will be used.  
#  
# [_:min\_span_ =\> int] The value _int_ indicates the minimum span of  
days which will  
# be collapsed into hyphenated form. The default is 3, as specified  
by the Quiz spec  
#  
# [_:week\_start_ =\> int] The value _int_ must be in the range (1, 7).  
#  
def to\_s(options={})  
names = get\_names\_override(options)  
#puts “Debug: @day\_names=#{@day\_names.inspect}, names=#{names}”  
min\_span = DayRange.get\_option(:min\_span, options, @min\_span)  
week\_start = DayRange.get\_option(:week\_start, options, @week\_start)

```
	result = ""
	adjusted_ranges(min_span,week_start).map {|range|
		range.first == range.last ?
                           "#{names[ws_unadj(range.first, 

```

week\_start)]}" :  
“#{names[ws\_unadj(range.first,  
week\_start)]}-#{names[ws\_unadj(range.last,week\_start)]}”  
}.join(", ")  
end

```
private
    # convert a number where 1 = Mon.. 7 = Sunday to the equivalent
# when the week starts on day number
def ws_adj(number, week_start)
	((number - week_start) % 7) + 1
end

# convert a number back to the original form
def ws_unadj(number, week_start)
	((number + week_start + 5) % 7) + 1
end

def extract_options_from_args!(args)
	#puts "Debug - extract_options_from_args!(#{args.inspect})"
	#puts " #{args.last.class}"
	StringSymHash[args.last.kind_of?(Hash) ? args.pop : {}]
end

def day_map_from_options(options)
	#puts "Debug: language=#{DayRange.language_from_options(options)}"
        #puts " 

```

map=#{@@day\_maps[DayRange.language\_from\_options(options)]}"  
DayRange.get\_option(:day\_map, options,  
@@day\_maps[DayRange.language\_from\_options(options)])  
end

```
def week_start_from_options(options, day_map)
	week_start = DayRange.get_option(:week_start, options, 1)
	week_start = day_map[week_start] || week_start
	DayRange.check_arg((1..7) === week_start,":week_start must be in the

```

range (1…7)")  
week\_start  
end

end

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
