0
\$\begingroup\$

This code converts a 3-letter English month abbreviation to its numeric equivalent (as a string).

public static String numericMonth(String monthInFull) {
  monthInFull = monthInFull.toUpperCase();
  if (monthInFull.equals("JAN")) { return "01"; }
  if (monthInFull.equals("FEB")) { return "02"; }
  if (monthInFull.equals("MAR")) { return "03"; }
  if (monthInFull.equals("APR")) { return "04"; }
  if (monthInFull.equals("MAY")) { return "05"; }
  if (monthInFull.equals("JUN")) { return "06"; }
  if (monthInFull.equals("JUL")) { return "07"; }
  if (monthInFull.equals("AUG")) { return "08"; }
  if (monthInFull.equals("SEP")) { return "09"; }
  if (monthInFull.equals("OCT")) { return "10"; }
  if (monthInFull.equals("NOV")) { return "11"; }
  if (monthInFull.equals("DEC")) { return "12"; }
  return "";
}

Is it possible to create an array (or Enum?) listing the month names and their respective index (or index + 1) and avoid this excess of if?

\$\endgroup\$
4
  • \$\begingroup\$ Using a switch statement would remove much of the repetition in your code. Whether or not using an enum here is beneficial or appropriate would require more context for how/where this code is being used. \$\endgroup\$
    – AJNeufeld
    Nov 18 '21 at 22:06
  • \$\begingroup\$ (monthInFull for three-letter abbrev.s is kind of odd. That's not a static String, but a static String method.) Please mention that run time is absolutely no concern. \$\endgroup\$
    – greybeard
    Nov 19 '21 at 8:08
  • 1
    \$\begingroup\$ The new switch expression: return switch (monthFull.toUpperCase()) { case "JAN" => "01"; case "FEB" => "02"; ... };} \$\endgroup\$
    – Joop Eggen
    Nov 19 '21 at 17:15
  • 1
    \$\begingroup\$ docs.oracle.com/javase/tutorial/datetime/iso/enum.html is a possible startup point. \$\endgroup\$ Nov 19 '21 at 19:48
3
\$\begingroup\$

Some improvement ideas:

  1. You could consider using java.time api, however to use DateTimeFormatter you'd have to use builder, quite heavily configure it (as it would require defaults for year and day, not to mention its case sensitive) and Month class does not seem to offer anything to help here - the benefit of this approach would be that you don't have to maintain localized list of months (but would end up with a date from which month would have to be extracted - additional step, unless there is some other way that I don't see)
  2. For current solution you can use map (like Map.of("JAN", 1, "FEB", 2...) and instead of repeating if have one get (or getOrDefault if you want to return default value, but...)
  3. I'd propose to throw exception instead of returning empty string for month out of bounds - I am not sure of exact use case but I'd prefer to know when something unexpected is happening in my code rather than continue execution (fail fast)
  4. Consider using String.format("%02d", parsedMonthNumber) instead manually prepending zeros to numbers - not that it is important in any way (can be even considered unnecessary complication) but this way you separate a little your "app logic" (parsing month number) from "display logic" (or are better of if such separation was ever needed - benefit of such separation is that you can use integer for number instead of string)

Edit: ad. 1 you could also use Month.values() check if name contains your raw month string and getValue - limiting yourself to english representations of months... but it kinda feels a little off

\$\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.