Does Mathematica have a built-in date picker?
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]
Style["Month ",FontSize->16],PopupMenu[Dynamic@month, Range@12 ]
}],
Dynamic@calendarView[month, year],
Panel[Dynamic@StringForm["Selected date: `1`/`2`/`3`", date, month, year]]
}]
]
]
]
There is a built-in DateSetter
:
{Developer`DateSetter[Dynamic@date], Dynamic@date}
By default the first selectable date is tomorrow and one can only go to future months. However, the option NotebookTools`DateSetterRange
can be used to set the first selectable date to sometime in the past,
{Developer`DateSetter[Dynamic@date, NotebookTools`DateSetterRange -> {2015, 1, 1}],
Dynamic@date}
or to only allow a certain date range.
{Developer`DateSetter[Dynamic@date,
NotebookTools`DateSetterRange -> {{2015, 1, 1}, {2015, 5, 2}}],
Dynamic@date}
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[date_List]:=DateString[date,{"DayNameShort"}]/.Thread[dayNames[]->Range[0,6]];
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];
Button[Dynamic[Graphics[{Lighter[Red,.3],Rectangle[{0,.6},{1,1},RoundingRadius->.1],
White,Rectangle[{0,0},{1,.5},RoundingRadius->.1],
Rectangle[{0,.3},{1,0.7}],
EdgeForm[GrayLevel[0.4]],FaceForm[],Rectangle[{0,0},{1,1},RoundingRadius->.1],
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"];
tmpdate=DialogInput[Dynamic@Style[Grid[Join[{{Row[{Button[Style["\[LeftPointer]\[LeftPointer]",Medium,Bold,FontFamily->"Helvetica"],tmpdate=DatePlus[tmpdate,{-1,"Year"}],ImageSize->All,Appearance->None],
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]
]