## Does Mathematica have a built-in date picker?

38

19

Does Mathematica have an interactive date input control that lets the user choose a date by browsing to a calendar view and returning the selected date as a date list? For example, something like the Datepicker in jQuery.

1No, it doesn't. But it shouldn't be difficult to build one using the basic controls that are available. – Sjoerd C. de Vries – 2012-12-18T15:35:30.563

Maybe a starting point here.

– b.gates.you.know.what – 2012-12-18T16:05:42.867

There is also some Wolfram examples with date pickers but looks like @rm -rf has delivered :) – Mike Honeychurch – 2012-12-18T20:52:34.000

4

I don't know if it is smart about about picking dates, but there is this for finding stable marriages. (Or did you mean to pick dates from trees? That part was ambiguous...)

– Daniel Lichtblau – 2013-01-02T16:39:46.343

38

### Date-picker implementation in Mathematica

The following is my implementation of a simple date-picker. The current date is highlighted in LightBlue and the weekends are highlighted in LightGreen. The selected date is always highlighted in LightRed (the default selection is the current date).

You can tap into this calendar by using the Dynamic values for year, month and date for your custom function (a simple example in the last Panel).

### Code:

Note that the following implementation uses DayName, which was introduced in version 9. You might have to roll your own if you want to use this in earlier versions of Mathematica.

With[{startDayOffset = Thread[{Sunday, Monday, Tuesday, Wednesday, Thursday,
Friday, Saturday} -> Range@7]},
DynamicModule[{month, year, date, today = DateList[][[;;3]], daysInMonth, calendarView},

{year, month, date} = today;

daysInMonth[m_Integer,y_Integer] := DatePlus[{y, m, 1}, {{1, "Month"}, {-1, "Day"}}][[3]];

calendarView[m_Integer, y_Integer] := Grid[
{Style[#, FontWeight -> Bold]& /@ {"Su","M","Tu","W","Th","F","Sa"}} ~Join~
Partition[Range@daysInMonth[m, y], 7, 7, {DayName[{y, m, 1}] /. startDayOffset, 1}, {""}],
Frame -> All,
FrameStyle -> LightGray
] /. { i_Integer :> Button[
i,
date=i,
Appearance->"Palette",
Background -> Which[
date==i, LightRed,
{year, month, i} === today, LightBlue,
!FreeQ[DayName[{year, month, i}],Saturday|Sunday],LightGreen,
True,White
],
ImageSize->{32,32}
],
s_String :> Button[
s,
,
Appearance -> "Palette",
Enabled -> False,
Background -> If[!s == "", LightGray],
ImageSize->{32,32}
]
};

Panel[
Column[{
Row[{
Style["Year ",FontSize->16], PopupMenu[Dynamic@year, 1970 ~Range~ 2020],Spacer[10]
}],
Dynamic@calendarView[month, year],
Panel[Dynamic@StringForm["Selected date: 1/2/3", date, month, year]]
}]
]
]
]


6+1 That's a really nice bit of Mathematica code. And, unlike the Mayan calendar, it doesn't stop in a couple of days. – cormullion – 2012-12-19T09:16:45.873

1No month rules, leap year stuff and data necessary if you just use DatePlus[date, {{1, "Month"}, {-1, "Day"}}][[3]], with date the first of the month you're interested in. – Sjoerd C. de Vries – 2012-12-20T22:50:34.047

@SjoerdC.deVries Thanks, that's much better :) Updated – rm -rf – 2012-12-21T04:05:54.260

20

There is a built-in DateSetter:

{DeveloperDateSetter[Dynamic@date], Dynamic@date}


By default the first selectable date is tomorrow and one can only go to future months. However, the option NotebookToolsDateSetterRange can be used to set the first selectable date to sometime in the past,

{DeveloperDateSetter[Dynamic@date, NotebookToolsDateSetterRange -> {2015, 1, 1}],
Dynamic@date}


or to only allow a certain date range.

{DeveloperDateSetter[Dynamic@date,
NotebookToolsDateSetterRange -> {{2015, 1, 1}, {2015, 5, 2}}],
Dynamic@date}


+1. Do you know which versions have this function? – Michael E2 – 2015-11-07T21:58:22.300

@MichaelE2 No, I don't know. I'm only aware that version 9.0.1 already has it, but without proper functioning. – Karsten 7. – 2015-11-07T23:09:57.220

Note this comment by JxB. Apparently their answer was inspired by this but it supposedly crashes the frontend.

– rm -rf – 2015-11-08T17:28:57.367

1This has no way to visit past months, but for me it's reliable so long as I only need the present or future. – Michael Stern – 2016-05-27T17:16:00.047

@MichaelStern By default the first selectable date is tomorrow and one can only go to future months. However, there is the option NotebookToolsDateSetterRange. I'll add two examples how it can be applied to my answer. – Karsten 7. – 2016-05-27T17:48:32.517

It doesn't work with a custom setter like DeveloperDateSetter[Dynamic[date,(date=#)&]] so it's not fully working yet. – faysou – 2016-05-27T18:51:57.737

12

Here is one that should work in version 6 and later. The full code is at bottom.

Here is what it looks like:

{dateSetter[Dynamic[d]],Dynamic[d]}


I did not incorporate the year here, but you could put it in a Tooltip or add it to the button's graphic.

And when you click on the button you get

Incorporate this into a Manipulate using {d,dateSetter[#]&} as a control:

Manipulate[DynamicModule[{difference},
difference=DateDifference[DateList[][[1;;3]],d];Style[Row[{DateString[d,{"DayShort"," ","MonthName"," ","Year"}]," ",difference/.{x_/;x<-1:>Row[{"was ",-x," days ago."}],
x_/;x==-1->"was yesterday.",
x_/;x==0->"is today.",
x_/;x==1->"is tomorrow.",
x_:>Row[{"is ",x," days from now."}]}}],"Text"]],{{d,DateList[][[1;;3]],""},dateSetter[#]&}]


The code:

Clear[monthDays];
monthDays[year_,month_]:=DateDifference[DateList@{year,month},DateList@{year,month+1}];
monthDays[date_List/;Length@date<=6]:=monthDays[date[[1]],date[[2]]];
monthDays[date_String]:=monthDays@@DateList[date][[1;;2]];

Clear[monthDates];
monthDates[year_,month_]:=DatePlus[DateList@{year,month,0},#]&/@Range[monthDays[year,month]];
monthDates[date_List/;Length@date<=6]:=monthDates[date[[1]],date[[2]]];
monthDates[date_String]:=monthDates@@DateList[date][[1;;2]];

Clear[dayNames];
dayNames[]=DateString[{0,0,#},"DayNameShort"]&/@Range[-1,5];

Clear[dayOfWeek];
dayOfWeek[year_,month_]:=dayOfWeek[{year,month,1}];

Clear[previousMonth];
previousMonth[year_,month_]:=Take[monthDates[year,month][[All,3]],-dayOfWeek[year,month]];

Clear[nextMonth];
nextMonth[year_,month_]:=Take[monthDates[year,month+1][[All,3]],7-dayOfWeek[year,month+1]];

Clear[monthArray];
monthArray[year_,month_]:=Module[{array},array=Partition[Join[Button[Style[#,Gray,Bold,FontFamily->"Helvetica"],Appearance->None,ImageSize->All,Enabled->False]&/@previousMonth[year,month],Button[Style[#,Darker[Cyan,.4],Bold,FontFamily->"Helvetica"],DialogReturn[{year,month,#}],Appearance->None,ImageSize->All]&/@monthDates[year,month][[All,3]],Button[Style[#,Gray,Bold,FontFamily->"Helvetica"],Appearance->None,ImageSize->All,Enabled->False]&/@nextMonth[year,month]],7,7,1,{}];
If[Length@array<6,Append[array,ConstantArray[Button[Style["",Gray,Bold,FontFamily->"Helvetica"],Appearance->None,ImageSize->All,Enabled->False],7]],array]]

Clear[dateSetter];
dateSetter[Dynamic[date_]]:=DynamicModule[{tmpdate,mousepos,storeddate},
If[Length@date<3,date=storeddate=tmpdate=DateList[][[1;;3]],tmpdate=storeddate=date];
Rectangle[{0,.3},{1,0.7}],
White,Text[Style[DateString[storeddate,{"MonthNameShort"}],Bold,FontFamily->"Helvetica"],{0.5,0.85}],
GrayLevel[0.3],Text[Style[DateString[storeddate,{"DayShort"}],Bold,FontFamily->"Helvetica",FontSize->Scaled[.5]],{0.5,0.35}]},
ImageSize->40]],
mousepos=MousePosition["ScreenAbsolute"];
Button[Style["\[LeftPointer]",Medium,Bold,FontFamily->"Helvetica"],tmpdate=DatePlus[tmpdate,{-1,"Month"}],ImageSize->All,Appearance->None]},Spacer[3]],
Style[DateString[tmpdate,{"MonthName"," ","Year"}],Bold,FontFamily->"Helvetica",Medium],
SpanFromLeft,SpanFromLeft,SpanFromLeft,SpanFromLeft,
Row[{Button[Style["\[RightPointer]",Medium,Bold,FontFamily->"Helvetica"],tmpdate=DatePlus[tmpdate,{1,"Month"}],ImageSize->All,Appearance->None],
Button[Style["\[RightPointer]\[RightPointer]",Medium,Bold,FontFamily->"Helvetica"],tmpdate=DatePlus[tmpdate,{1,"Year"}],ImageSize->All,Appearance->None]},Spacer[3]]}},
{Style[#,FontFamily->"Helvetica",Medium]&/@dayNames[]},
monthArray[tmpdate[[1]],tmpdate[[2]]]],Background->{{None},{GrayLevel[0.8]}},Frame->True,Spacings->{.5,.5}],Small,FontFamily->"Helvetica"],
WindowMargins->{{mousepos[[1]],Automatic},{Automatic,mousepos[[2]]}},WindowElements->None,WindowFloating->True];
If[tmpdate=!=\$Failed,date=storeddate=tmpdate,tmpdate=date],Method->"Queued",
Appearance->None]
]


The appearance and functionality is inspired by DeveloperDateSetter[], pointed out to me by @WReach. That function is not documented, and it crashes my front end session quite reliably. – JxB – 2013-01-02T09:33:54.100

I think that you forgot to include the monthDates definition. – Gustavo Delfino – 2013-01-02T17:56:38.793

@GustavoDelfino It's there right after the Clear[monthDates]. – JxB – 2013-01-02T18:36:25.987

Thank you @JxB. I fell victim to the invisible scroll bars in Mac OS X. – Gustavo Delfino – 2013-01-04T16:20:05.617

2

Here's a silly one that works only in version 9:

DynamicModule[{x = 0}, AngularGauge[Dynamic[x], {0, 365},
GaugeFrameStyle -> Black,
GaugeFrameSize -> .01,
ScaleDivisions -> 0,
GaugeFaceStyle -> Directive[LightGreen, EdgeForm[]],
GaugeFaceElementFunction -> "PlateauSector",
GaugeLabels ->
Dynamic[
Style[
DateString[
DatePlus[{2013, 1, 1}, x], {"DayName",   " ", "MonthName", " ",
"Day" , ", ", "Year"}], 10 , Bold, Gray]]]]
`