• Coding
  • [Exercise]Time converter

The goal of this exercise is to focus on code conciseness. If anyone feels like Code Golfing, be my guest, but I'm giving the exercise in such a way that's far from optimal for golf. More importantly, your focus should be on the expressivness of your algorithms, and work on this with as few lines of codes as possible.

The converter will convert between time measuring units. They are:

- seconds
- minutes
- hours
- days
- months
- years

The input is a string that follows this pattern:
<X> <unit1> in <unit2>?

//For instance:

1000000 days in years?
or 
33 hours in months?
Bonus points
Avoid giving floating numbers as an answer. You should instead decompose it in successively lower elements. In this aspect, "33 hours in months?" should not return "0.0458333" instead it should return "1 day 9 hours". I hope this is clear enough.

Conversion rates
The Gregorian Calendar is fundamentally stupid and wrong. It is littered with inconsistencies that would pollute the exercise. In order to avoid useless work, let's just focus on simple conversion rates, for the sake of this exercise:

1 year = 12 months = 360 days (I know...)
1 month = 30 days
1 day = 24h
1 hour = 60 minutes
1 minute = 60 secs.

Now, once you're done with your exercise, maybe you can tell me why we are still using this broken calendar system?
values = {1, 60, 60, 24, 30, 12};
names = {"second", "minute", "hour", "day", "month", "year"};
Do[values[[i]] *= values[[i - 1]], {i, 2, Length@values}]

(unit[#[[1]]] = #[[2]]) & /@ Partition[Riffle[names, values], 2];
(position[#[[1]]] = #[[2]]) & /@ Partition[Riffle[names, Range[Length@names]], 2];

h[ds_] := Module[
  {r},
  r = StringJoin[
    Reverse@MapIndexed[
      If[#1 > 0, ToString@#1 <> " " <> names[[#2]] <> If[#1 > 1, "s ", " "], ""] &,
      ds]
  ];
  If[r != "", StringDrop[r, -1], ""]
];

f[t_, u_: 0, z_: {}] := If[u == 0,
  z,
  f[Mod[t, values[[u]]], u - 1, Prepend[z, Quotient[t, values[[u]]]]]
];

g[s_] := With[
  {tokens = StringSplit[s]},
  f[ToExpression[tokens[[1]]] unit[StringDrop[tokens[[2]], -1]], position[StringDrop[tokens[[4]], -2]]]
];
is = {"1000000 days in years?", "33 hours in months?", "0 seconds in years?", "1 years in years?", "9876543210 seconds in years?"};
g /@ is
h /@ g /@ is

{{0, 0, 0, 10, 9, 2777}, {0, 0, 9, 1, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1}, {30, 13, 20, 11, 6, 317}}
{"2777 years 9 months 10 days", "1 day 9 hours", "", "1 year", "317 years 6 months 11 days 20 hours 13 minutes 30 seconds"}