2
$\begingroup$

I have a list of dates in one of the following formats: "1999/05/12", "1999/05/", "1999//", "****//**/", ""

so that a list of such dates might appear as

col4n = {"1992/05/12", "1979/03/**", "1970/**/**", "****/**/**", "", Null};

I want to convert these using a date function that will display these dates in an alternate format, namely {"12 May 1992", "Mar 1979", "1970", "", "", ""} for printing to a file.

To do this I have created an overloaded datefun[x_String, /; x== format-] as follows:

datefun[x_String /; x == "****/**/**"] = Module[{y}, y = Null;];

datefun[x_String  /; StringMatchQ[x, RegularExpression["\\d+/**/**"]] ] := 
Module[{y, y1}, y = x; y1 = StringTake[ToExpression[y], 4]; 
y =  StringReplace[y1, DateString["Year"]]];

datefun[x_String /;     StringMatchQ[x, RegularExpression["\\d+/\\d+/**"]]]    :=   Module[{y, y1, y2}, y = x; y1 = StringTake[x, 4]; y2 = StringTake[y, {6,7}]; 
y = StringReplace[DateList[y], 
 DateString[y2, "MonthNameShort"] <> " " <> 
  DateString[y1, "Year"]]];

datefun[x_String /; 
StringMatchQ[x, RegularExpression["\\d+/\\d+/\\d+"]] ] := 
Module[{y}, y = x; 
 y = DateString[
 DateList[y], {"DayShort", " ", "MonthNameShort", " ", "Year"}]];

datefun[x_String /; StringMatchQ[x, Null]] := Module[{y}, y = Null];

datefun[x_String /; StringMatchQ[x, ""]] := Module[{y}, y = ""];

to handle each of the varying cases.

However, when I go to Map this across my list:

col4n = Map[datefun, col4n] // Quiet

Only those dates for which a complete date or no date at all are handled correctly.

It would seem that either I have a problem with my regular expression not matching the "incomplete" dates properly or there is a problem with the DateList function not correctly handling these "incomplete" dates or both, which I suspect is the case as I note that in some cases, where I have tried to decompose the functions, DateList returns missing values with a "1" for missing months or days of the month rather than not returning anything at all as I would expect. Unfortunately, various attempts to flail have me seeking help.

How can I correct my code to perform these conversions for these "incomplete" dates into the format I want?

$\endgroup$
2
$\begingroup$

This approach converts to the strings to a valid date spec and then applies the formatting. It has no overloaded versions and does not dependent on the placeholder character. It is a chain of Map (/@) and Prefix (@) so read from the bottom up. There are some double Maps as well (Map[__] /@).

dateStringFormat[dates_List] :=
 ReplaceAll[{
       {{s : __}, {t : __}} :> DateString[{t}, Riffle[{s}, " "]], 
       {{}, {}} -> ""}]@
    With[{len = Length@#},
     {
      {If[len == 3 \[And] Positive@#[[3]], "Day", Nothing],
       If[len >= 2 \[And] Positive@#[[2]], "MonthNameShort", Nothing],
       If[len >= 1 \[And] Positive@#[[1]], "Year", Nothing]},
      # /. {0 -> Nothing}
      }] & /@
  Map[FromDigits] /@
   Map[ReplaceAll[(v_ /; Not@StringMatchQ[v, DigitCharacter ..]) -> ""]] /@
    StringSplit[dates /. Null -> "", "/"]

col4n = {"1992/05/12", "1979/03/**", "1970/**/**", "****/**/**", "", Null};
dateStringFormat[col4n]

{"12 May 1992", "Mar 1979", "1970", "", "", ""}

Hope this helps.

$\endgroup$
  • $\begingroup$ Thank you. Most definitely helps, although I am still working my way through the logic of the second approach to understand how it arrives at the solution. Clearly, the first approach is much more straightforward, but not as catholic as the second. $\endgroup$ – Stuart Poss Jan 8 '16 at 22:10
1
$\begingroup$
Clear@ConvertDate

ConvertDate[s_String] /; StringCount[s, "*"] == 0 :=
 DateString[s, {"Day", " ", "MonthNameShort", " ", "Year"}]

ConvertDate[s_String] /; StringCount[s, "*"] == 2 :=
 DateString[s, {"MonthNameShort", " ", "Year"}]

ConvertDate[s_String] /; StringCount[s, "*"] == 4 :=
 DateString[s, {"Year"}]

ConvertDate[s_String] := ""

ConvertDate[""] := ""

ConvertDate[Null] := Null

col4n = {"1992/05/12", "1979/03/**", "1970/**/**", "****/**/**", "", Null};

ConvertDate /@ col4n

{"12 May 1992", "Mar 1979", "1970", "", "", Null}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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