12
$\begingroup$

It is known that CharacterRange["a", "z"] gives list of characters from a to z. Does Mathematica have something similar for weekdays and months of the year? Something like:

Somefunction["Saturday", "Friday"]
(* {"Saturday", "Sunday", ...} *)

Somefunction["January", "December"]    
(* {"January ", "February ", ...} *)
$\endgroup$
7
  • $\begingroup$ Maybe you should clarify "Week Days": dict.leo.org/forum/…. And why start with "Saturday"? As far as I know a new week starts in the United States with Sunday, whereas in most European countries it's Monday. Aside from this a +1 question :) $\endgroup$
    – eldo
    Aug 6, 2014 at 21:23
  • $\begingroup$ @eldo, Just random selection of days :) $\endgroup$ Aug 6, 2014 at 21:40
  • $\begingroup$ Agree, Like the "French Republican Calendar". $\endgroup$
    – eldo
    Aug 6, 2014 at 22:52
  • 3
    $\begingroup$ If you didn't find it in the documentation it's probably not there. With all due respect I think this is just a way of asking for an implementation without having to respond to the question "what did you try?" $\endgroup$
    – C. E.
    Aug 6, 2014 at 23:03
  • 1
    $\begingroup$ @Pickett I think you know that there are so many things undocumented. I am not trying anything other than finding some way to get things done easier. I am still learning MMA and I am not aware of so many things in this program :) $\endgroup$ Aug 7, 2014 at 0:13

3 Answers 3

14
$\begingroup$

For full ranges

There is the function DayRange that can be used for this purpose, but not in the same simple way like CharacterRange.
For the days:

DayName /@ DayRange[Today, Today ~DatePlus~ {{1, "Week"}, {-1, "Day"}}]
{Wednesday, Thursday, Friday, Saturday, Sunday, Monday, Tuesday}

For the months:

DateValue[#, "MonthName"] & /@ DayRange[Today, Today ~DatePlus~ {1, "Year"}] // DeleteDuplicates
{"August", "September", "October", "November", "December", "January", "February", "March", "April", "May", "June", "July"}

If you need a special order, Today can be replaced with a suitable DateObject.


Or shorter and faster for the month range:
Day Range:

DayName[DateObject[{2014, 09, #}]] & /@ Range[7]
{Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}

Month Range:

(DateValue[#, "MonthName"] &@DateObject[{2014, #, 01}]) & /@ Range[12]
{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}

For arbitrary ranges

For arbitrary month ranges:

monthRange[month1_String, month2_String] :=
 Module[{m1 = DateList[month1][[;; 2]], m2 = DateList[month2][[;; 2]], i},
  Reap@For[i = 0,
   DateValue[m1 + i, "MonthName"] != DateValue[m2, "MonthName"],
   i++,
   Sow@DateValue[m1 + i, "MonthName"]
   ] // Last // Flatten // Append[month2]
 ]

For arbitrary day ranges:

dayRange[day1_String, day2_String] :=
 Module[{date1 = (DateList@DayPlus[Today, 1, Symbol[day1]])[[;; 3]], day2Symbol = Symbol[day2], i},
  Reap@For[i = 0,
   DayName@(date1 + {0, 0, i}) != day2Symbol,
   i++,
   Sow@ToString@DayName@(date1 + {0, 0, i})
   ] // Last // Flatten // Append[day2]
 ]

and the function overload for symbolic days

dayRange[day1_Symbol, day2_Symbol] :=
 Module[{date1 = (DateList@DayPlus[Today, 1, day1])[[;; 3]], i},
  Reap@For[i = 0,
   DayName@(date1 + {0, 0, i}) != day2,
   i++,
   Sow@DayName@(date1 + {0, 0, i})
   ] // Last // Flatten // Append[day2]
 ]

And for those who can't stand procedual programming

monthRange2[month1_String, month2_String] :=
 Module[{d1 = DateList[month1][[2]], d2 = DateList[month2][[2]], range},
  range = If[d2 < d1, Range[d1, 12 + d2], Range[d1, d2]];
  (DateValue[#, "MonthName"] & @ DateObject[{2014, #, 01}]) & /@ range
]

and

dayRange2[day1_String, day2_String] :=
 Module[{date1 = DayPlus[Today, 1, Symbol@day1], date2},
  date2 = DayPlus[date1 ~DayPlus~ -1, 1, Symbol@day2];
  ToString@*DayName /@ date1 ~DayRange~ date2
]

with the overload

dayRange2[day1_Symbol, day2_Symbol] :=
 Module[{date1 = DayPlus[Today, 1, day1], date2},
  date2 = DayPlus[date1 ~DayPlus~ -1, 1, day2];
  DayName /@ date1 ~DayRange~ date2
]
$\endgroup$
7
$\begingroup$

1) Get the list of days and months. Note that days are represented in MMA as symbols (and not strings as months are), hence the use of ToString to make them in a consistent type with the list of months (credit to @Mr.Wizard for this tip).

monthList=DateValue[{2014,#,1},"MonthName"]&/@Range[12]
(* {January,February,March,April,May,June,July,August,September,October,November,December} *)

dayList=DateValue[{2014,1,#},"DayName"]&/@Range[7]//Map[ToString,#]&
(* {Wednesday,Thursday,Friday,Saturday,Sunday,Monday,Tuesday} *)

2) Define a function that take a starting month and an ending month. Rotate month list until the first month of the list is the defined starting month. Then, trim the months after the ending month.

Clear[monthRange]
monthRange[start_?(MemberQ[monthList,#]&),end_?(MemberQ[monthList,#]&)]:=Module[{rotated},
rotated=NestWhile[RotateLeft,monthList,(First@#!=start&)];
rotated/.{a___,end,b___}:>{a,end}]

monthRange["March","January"]
(* {March,April,May,June,July,August,September,October,November,December,January} *)

3) Do the same for the day list.

Clear[dayRange]
dayRange[start_?(MemberQ[dayList,#]&),end_?(MemberQ[dayList,#]&)]:=Module[{rotated},
rotated=NestWhile[RotateLeft,dayList,(First@#!=start&)];
rotated/.{a___,end,b___}:>{a,end}]

dayRange["Wednesday","Monday"]
(* {Wednesday,Thursday,Friday,Saturday,Sunday,Monday} *)
$\endgroup$
12
  • $\begingroup$ Interesting approach. :-) If I had known you were writing this I might not have written mine. FYI: You can use RotateLeft in place of RotateLeft[#,1]&. $\endgroup$
    – Mr.Wizard
    Aug 6, 2014 at 23:08
  • $\begingroup$ Thanks for the tip! Appreciate the compliment especially coming from you. $\endgroup$
    – seismatica
    Aug 6, 2014 at 23:12
  • 1
    $\begingroup$ If I come up with something good I'll include it in your answer, but it will probably be tomorrow. Here's a teaser of one method, should you choose to use it yourself: Join[#, #] & @ monthList /. {___, seq : PatternSequence["October", ___, "May"], ___} :> {seq} $\endgroup$
    – Mr.Wizard
    Aug 6, 2014 at 23:22
  • 1
    $\begingroup$ @eldo I came up with the first step on my own and as far as I could recall my answer was posted before Karsten's edit to add the quick method at the end. Both methods generate the same list of dates and months, though mine also include functions to find the range between 2 arbitrary momths/days. Please let me know what I can improve on in my answer and I'd be more than happy to accommodate. $\endgroup$
    – seismatica
    Aug 7, 2014 at 0:33
  • 2
    $\begingroup$ @eldo my "faster" edit and seismatica's answer where posted within seconds. No one stole that from anyone. Moreover our approaches are quite different. +1 (+ I thought the OP just wanted "a" to "z" or rather "January" to "December") $\endgroup$
    – Karsten7
    Aug 7, 2014 at 1:10
7
$\begingroup$

It's fun to use Associations as a circular linked list, which automatically handles the cyclic nature of these ranges:

Clear@monthRange
monthRange[start_, end_] := Module[{monthsLL, head},
    monthsLL = Fold[
        <|#2 -> #|> &,    
        Reverse[DataPaclets`CalendarDataDump`MonthList["Gregorian"] ~Join~ {monthsLL}]
    ];
    head = NestWhile[First, monthsLL, Keys@# != {start} &];
    NestWhileList[First, head, Keys@# != {end} &] // Keys /* Flatten
]

You can use any other list (e.g. days of week) instead of DataPaclets`CalendarDataDump`MonthList to create a similar "range" function.

monthRange["December", "April"]
(* {"December", "January", "February", "March", "April"} *)

monthRange["March", "August"]
(* {"March", "April", "May", "June", "July", "August"} *)

You can also define the linked list outside the function instead of creating it each time, if performance is critical. For most use cases, this will not be an issue.

$\endgroup$
4
  • $\begingroup$ +1, Very nice to see the undocumented things is there any thing similar to DataPaclets`CalendarDataDump`MonthList for week list? that would be the perfect answer for this question. $\endgroup$ Aug 7, 2014 at 23:28
  • $\begingroup$ I would also be grateful if you tell me where to find these undocumented functions of mathematica. where and how do you get them? :) $\endgroup$ Aug 7, 2014 at 23:31
  • 1
    $\begingroup$ @Algohi There are only 7 days in a week... I'm sure you can type it out faster than hunting for DataPaclets`... (if it existed). I was just too lazy to type out all the months :) Here, use this: Thread[{"Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur"} ~~ "day"] $\endgroup$
    – rm -rf
    Aug 7, 2014 at 23:35
  • $\begingroup$ yes you are right :) :) :). you know, It is some times fun to know how to do things differently even if they are simple and also it is good to know the hidden parts in MMA. :) $\endgroup$ Aug 8, 2014 at 0:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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