[Question]
  [
In Vernor Vinge's excellent and fascinating book *A Deepness in the Sky*
(which, by the way, I highly recommend1), the *Qeng Ho*, a culture
that spans various star systems, has no notion of "days," "months," "years,"
etc., and hence has a unique timekeeping system that measures time entirely in
seconds. The most commonly used units are the *Ksec* (kilosecond), *Msec*
(megasecond), and *Gsec* (gigasecond). Here's a handy chart from my own copy of
the book (since I can't find it online):
![handy chart](https://i.stack.imgur.com/v58ra.png)
You are currently flying on the *Pham Nuwen*, and you have just received a
message from a strange, unknown planet called "*Earth*."2 They use different
time units than you do, and your computers don't recognize theirs. As the
resident Programmer-Archaeologist of the ship, your job is to patch the
time-handling code so that it recognizes *Earth* units of time.
Naturally, since you're only out of coldsleep for another few Ksecs, you want
to make your code as short as possible so it can be written quickly.
Fortunately, as an interstellar trading culture, the Qeng Ho has access to
every programming language invented.
## Input
The input will be a single string containing one or more space-separated
*components*. A *component* is defined as an integer number > 0 and ≤ 255, then
a space, and then one of `second`, `minute`, `hour`, `day`, `week`, `month`,
`year`, `decade`, or `century`, possibly plural (with an added `s`, or
`centuries` for the last case).
Here are some valid example inputs:
```
10 days 12 hours
1 year
184 centuries 1 second
9 weeks 6 days 2 hours 1 minute 20 seconds
```
You may assume the following about the input:
* Pluralization of units will always agree with the relevant number.
* If there are multiple *components* in the input, they will always be in
descending order of length.
Here are what the various input units mean, for the purposes of this challenge:
```
unit     relative    absolute
---------------------------------------
second   1 second    1 second
minute   60 seconds  60 seconds
hour     60 minutes  3600 seconds
day      24 hours    86400 seconds
week     7 days      604800 seconds
month    30 days     2592000 seconds
year     365 days    31536000 seconds
decade   10 years    315360000 seconds
century  10 decades  3153600000 seconds
```
## Output
Here are the Qeng Ho units which your code has to support:
```
unit    relative      absolute
----------------------------------------
second  1 second      1 second
Ksec    1000 seconds  1000 seconds
Msec    1000 Ksecs    1000000 seconds
Gsec    1000 Msecs    1000000000 seconds
```
Use the following algorithm to determine your code's output:
* First, add up the total amount of time that the input represents.
* Find the largest Qeng Ho unit that is shorter or the same amount of time as
the input—essentially, find the largest unit that there is at least one of.
* Convert the total amount of time given in the input into this unit, and
output the result, rounded to three decimal places.
You may have your choice of which of the following methods to use: rounding up,
rounding down, rounding away from zero, or rounding towards ∞ or -∞. If the
rounded result ends in `0`, you may either remove trailing zeroes or keep as
many as you want (or do both, depending on the input).
If the rounded result is exactly `1.000`, you must use the singular form
(`second`, `Ksec`, `Msec`, `Gsec`); otherwise, use the plural form (`seconds`,
`Ksecs`, `Msecs`, `Gsecs`).
In certain edge-cases, you might be using the unit of, for example, Ksec, but
obtain a rounded result of 1000.000 Ksecs. In this case, you may simply output
`1000.000 Ksecs` instead of `1 Msec`.
You may always assume that the input is in descending order of units (century,
decade, year, etc.); furthermore, the component that comes after any given unit
will always be shorter (that is, `1 decade 20 years` is invalid input).
## Test cases
Note: results marked with an asterisk (`*`) may vary by a negligible amount due
to rounding differences.
```
input                                         output
-------------------------------------------------------------
1 hour                                        3.600 Ksecs
1 day                                         86.400 Ksecs
2 weeks                                       1.210 Msecs
1 year                                        31.536 Msecs
32 years                                      1.009 Gsecs   *
1 second                                      1.000 second
1 century 6 decades                           5.046 Gsecs   *
255 centuries                                 804.168 Gsecs
2 weeks 6 days 1 hour 19 minutes 4 seconds    1.733 Msecs
1 week 3 days 3 hours 7 minutes               875.220 Ksecs
1 week 4 days 13 hours 46 minutes 40 seconds  1.000 Msec
2 months 2 hours                              5.191 Msecs   *
16 minutes 39 seconds                         999.000 seconds
```
## Rules
* This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest code in bytes wins.
---
1: only if you like hard scifi, of course. In which case I recommend
reading *A Fire Upon the Deep* first, which is (in my opinion) even more
fantastic.
2: well, technically "Old Earth" is mentioned several times in *A Deepness in the Sky*, but...
  
[Answer]
# JavaScript (ES6) 255
```
f=s=>(s=s.replace(/(\d+) (..)/g,(_,n,u)=>t+={se:1,mi:60,ho:3600,da:86400,we:604800,mo:2592e3,ye:31536e3,de:31536e4,ce:31536e5}[u]*n,t=0),[a,b]=t>=1e9?[t/1e9,' Gsec']:t>=1e6?[t/1e6,' Msec']:t>999?[t/1e3,' Ksec']:[t,' second'],a.toFixed(3)+b+(a-1?'s':''))  
// test
console.log=x=>O.innerHTML+=x+'\n'
;[
 ['1 hour','3.600 Ksecs']
,['1 day','86.400 Ksecs']
,['2 weeks','1.210 Msecs']
,['1 year','31.536 Msecs']
,['32 years','1.009 Gsecs'] 
,['1 second','1.000 second']
,['1 century 6 decades','5.046 Gsecs']
,['255 centuries','804.168 Gsecs']
,['2 weeks 6 days 1 hour 19 minutes 4 seconds','1.733 Msecs']
,['1 week 3 days 3 hours 7 minutes','875.220 Ksecs']
,['1 week 4 days 13 hours 46 minutes 40 seconds', '1.000 Msec']
,['2 months 2 hours', '5.191 Msecs']
,['16 minutes 39 seconds', '999 seconds']
].forEach(t=>console.log(t[0]+' '+f(t[0])+' (Check:'+t[1]+')'))
```
```
<pre id=O></pre>
```
[Answer]
# [APL (Dyalog APL)](https://www.dyalog.com/), ~~157~~ ~~156~~ ~~154~~ ~~151~~ ~~154~~ ~~141~~ 142 bytes
```
{∊(3⍕N)' '((B/S⊃' KMG')'sec','ond'/⍨~B←T≥1E3),'s'/⍨1≠N←T÷1E3*S←⌊1E3⍟T←+/×/↑⍎¨'\d+ .a?i?'⎕S'&'⊢⍵⊣c←10×d←10×⊃y m w←365 30 7×da←24×h←×⍨mi←60×s←1}
```
Thanks to ngn for shaving off 13 bytes.
Must have `⎕IO←0`, which is default in many APLs.
[Try it online!](https://tio.run/nexus/apl-dyalog#VY/PSsNAEMbvPsWc3NYW82fTlJ4KBRERK6U9egnJQoMkhW5LCaIXodhgih5Kj4oi9AXEu3mTeZE4ySZWLzvffPubb3ZxvTm7xOWTng3ovMGHuMYx2fTrDFit1tOGGN8zOL84ZXUmhcuabBJ6TMNkd9ejgRGuPowTXm8yWZgGrl77uZ9@kX00JImPMUlMXkbUNLR0q@HyGZP1945deQ04drp@l@F6M2SHDOM3TD4xfneJNfR065WVXhFBAAtqud0CrkObLh1qTSvdjqkSk@wCn5RNvMznbrNsAMyA8WQ@ZQeF9JyoUCYshLiWpRsJRwHcLHTl04fz36rGFeFsPo3ABk@4jicUZLZa5Y1fOSo655xIgloPRgcCP5zPhASrzK225DhwRfOCltCu6L@MVSZWkGXvM/V/oSYEk3A2lmAqVKXscd75xX8A "APL (Dyalog APL) – TIO Nexus")
`{`…`}` "dfn"; argument is `⍵`:
 `s←` let `s` be 1
 `mi←60×` let `mi` be 60 times that (i.e. 60)
 `h←×⍨` let `h` be that squared (lit. that multiplied by itself, i.e. 3600)
 `da←24×` let `da` be 24 times that (i.e. 86400)
 `y m w←365 30 7×` let `y`, `m`, and `w` be 365, 30, and 7 times that, respectively (i.e. 31536000, 2592000, and 604800)
 `d←10×⊃` let `d` be 10 times the first of those (i.e. 315360000)
 `c←10×` let `c` be 10 times that (i.e. 3153600000)
 `⍵⊣` discard that in favour of the given argument
 `'\d+ .a?i?'⎕S'&'⊢` **S**earch for, and extract all runs of digits followed by a space, any character, optionally an "a", and optionally an "i"
 `⍎¨` execute each as APL code (gives pairs of counts and units in seconds)
 `↑` mix the pairs into a 2-column matrix.
 `×/` multiply along the rows, yielding a list of counts of seconds
 `T←+/` let `T` be the sum of those (the total count of seconds)
 `1E3⍟` \$\log\_{10}\$ of that
 `N←⌊` let `N` be the floor of that (i.e. the order of magnitude of `T`)
 `1≠` yield 1 if that is different from 1, but 0 otherwise
 `'s'/⍨` use that to replicate the letters of the string "s" (yielding "s" if we need a plural)
 `(3`…`3),` prepend the following three things:
  1. `3⍕N` the string consisting of `N` rounded to 3 decimal places
  2. `' '` a space
  3. `B←T≥1E3` let `B` be 1 if `T` is at least 1000, but 0 otherwise
     `~` logically negate that (i.e. 0 if `T` is at least 1000, but 1 otherwise)
     `'ond'/⍨` use that to replicate the string "ond" (for the full word if there's no prefix)
     `'(`…`)'sec',` prepend the 2-element list consisting of the following and the string "sec":
      `S⊃' KMG'` use `S` as an index to select a prefix from the string " KMG"
      `B/` replicate the letters of that by `B` (empty out `S` if `B` is 0, but leave as-is if it is 1)
 `∊` **e**nlist (flatten until a simple string)
[Answer]
# Python, ~~366~~ 363 bytes
```
d={};l=1;q=str.replace;i=q(raw_input(),"ie","y")
for u,t in zip('second minute hour day week month year decade century'.split(),(1,60,60,24,7,30./7,73./6,10,10)):l=t*l;d[u]=d[u+"s"]=l
while" "in i:
 i=q(q(i," ","*",1)," ","+",1)
q=eval(i,d);f={};l=1
for u in('second','Ksec','Msec','Gsec'):
 l*=1e3
 if q<l:q=q*1e3/l;print"%.3f %s%s"%(q,u,("s","")[q<1.001]);break
```
[Answer]
# SpecBAS - ~~476~~ 471 bytes
Because nothing says "cower before our technological superiority" better than line numbers and GOTO statements :-)
```
1 INPUT e$: DIM t$(SPLIT e$,NOT " "): DIM m=31536e5,31536e4,31536e3,2592e3,604800,86400,3600,60,1
2 LET q=0,n$=" cedeyemowedahomise"
3 FOR i=1 TO ARSIZE t$() STEP 2: LET t=VAL t$(i),u$=t$(i+1)( TO 2),p=POS(u$,n$)/2: INC q,t*m(p): NEXT i
4 IF q>=1e9 THEN LET r=q/1e9,r$=" G": GO TO 8
5 IF q>=1e6 THEN LET r=q/1e6,r$=" M": GO TO 8
6 IF q>999 THEN LET r=q/1e3,r$=" K": GO TO 8
7 IF q<1e3 THEN LET r=q,r$=" "
8 PRINT USING$("&.*0###",r);r$;"sec"+("ond" AND q<1e3)+("s" AND r>1)
```
[Answer]
# C# (in LinqPad as Function), 460 Bytes
```
void Main(){var x=Console.ReadLine().Split(' ');long s=0,v,i=0;for(;i<x.Length;){v=long.Parse(x[i++]);var w=x[i++].Substring(0,2);s+=w=="ce"?v*3153600000:w=="de"?v*315360000:w=="ye"?v*31536000:w=="mo"?v*2592000:w=="we"?v*604800:w=="da"?v*86400:w=="ho"?v*3600:w=="mi"?v*60:v;}decimal k=1000,m=k*k,g=m*k,r=0;var o="sec";r=s/g>=1?s/g:s/m>=1?s/m:s/k>=1?s/k:s;o=s/g>=1?"G"+o:s/m>=1?"M"+o:s/k>=1?"K"+o:o+"ond";Console.WriteLine(Math.Round(r,3)+" "+o+(r==1?"":"s"));}
```
ungolfed:
```
void Main()
{
    var x=Console.ReadLine().Split(' ');
    long s=0,v,i=0;
    for(;i<x.Length;)
    {
        v=long.Parse(x[i++]);
        var w=x[i++].Substring(0,2);
        s+=w=="ce"?v*3153600000:w=="de"?v*315360000:w=="ye"?v*31536000:w=="mo"?v*2592000:w=="we"?v*604800:w=="da"?v*86400:w=="ho"?v*3600:w=="mi"?v*60:v;
    }
    decimal k=1000,m=k*k,g=m*k,r=0;
    var o="sec";
    r=s/g>=1?s/g:s/m>=1?s/m:s/k>=1?s/k:s;
    o=s/g>=1?"G"+o:s/m>=1?"M"+o:s/k>=1?"K"+o:o+"ond";
    Console.WriteLine(Math.Round(r,3)+" "+o+(r==1?"":"s"));
}
```
[Answer]
# Mathematica ~~296~~ 281 bytes
`h`: After breaking up the input string into a list of quantity magnitudes and units, `Capitalize` and `Pluralize` convert the input units into Mathematica `Quantity`'s, from which the total number of seconds is derived.
`d` converts seconds to the appropriate units. The final `s` is removed if the time corresponds to 1 unit (of any kind).
With minor adjustments in the code, this approach should work for conversion of natural language input into any measurement system, conventional or not.
```
h=Tr[UnitConvert[Quantity@@{ToExpression@#,Capitalize@Pluralize@#2},"Seconds"]&@@@Partition[StringSplit@#,2]][[1]]&;
d=ToString[N@#/(c=10^{9,6,3,0})[[p=Position[l=NumberDecompose[#,c],x_/;x>0][[1,1]]]]]<>StringDrop[{" Gsecs"," Msecs"," Ksecs"," seconds"}[[p]],-Boole[Tr[l]==1]]&
z=d@h@#&;
```
---
Put into table form:
```
z1[n_]:={n,z@n}
Grid[z1 /@ {"1 hour", "2 day", "2 weeks", "1 year", "32 years", 
   "1 second", "1 century 6 decades", "255 centuries", 
   "2 weeks 6 days 1 hour 7 minutes", 
   "1 week 3 days 3 hours 46 minutes 40 seconds", 
   "1 week 4 days 13 hours 46 minutes 40 seconds", "2 months 2 hours",
    "16 minutes 39 seconds"}, Alignment -> Right]
```
[![pic](https://i.stack.imgur.com/v5KYQ.png)](https://i.stack.imgur.com/v5KYQ.png)
[Answer]
# Haskell, ~~565~~ 555 bytes
```
import Data.List
import Numeric
import Data.Bool
i=isPrefixOf
s x=showFFloat(Just 3)x""
r=read
f=fromIntegral
b=bool"s"""
c=b.(=="1.000")
h(c:u:l)
 |i"s"u=(r c)+h l
 |i"mi"u=(r c*60)+h l
 |i"h"u=(r c*3600)+h l
 |i"da"u=(r c*86400)+h l
 |i"w"u=(r c*604800)+h l
 |i"mo"u=(r c*2592000)+h l
 |i"y"u=(r c*31536000)+h l
 |i"de"u=(r c*315360000)+h l
 |True=(r c*3153600000)+h l
h _=0
q i
 |v<-s((f i)/10^9),i>=10^9=v++" Gsec"++c v
 |v<-s((f i)/10^6),i>=10^6=v++" Msec"++c v
 |v<-s((f i)/1000),i>=1000=v++" ksec"++c v
 |True=show i++" second"++b(i==1)
t=q.h.words
```
I'm reasonably sure I'm missing so many golfing opportunities here…The price of being a golfing beginner I guess.
My answer is a function taking a string containing the Earth time as an input parameter and returning the Qeng Ho time.
*P.S. :* I stupidly forgot about the 3 digits precision…which does drive the byte count up.
*P.P.S. :* Better chosen top-level expressions shaved off 10 bytes…and it should now be accurate to boot.
[Answer]
## Matlab 315 bytes
```
K='cedeyemowedahomiseconds';Q=' KMGT';for j=1:9;y(j)=double(~isempty(strfind(S,K(2*j-1:2*j))));end
y(y==1)=sscanf(S,repmat('%d %*s ',1,9));y=86400*sum(datenum([sum(y(1:3)*10.^[2;1;0]),y(4),y(5:6)*[7;1],y(7:9)]));z=floor(log10(y)/3);y=num2str(y/10^(3*z)+1e-4);[y(1:4),' ',Q(z+1),K(17:23-(y(1:4)=='1.00'))]
```
Test:
```
S = '2 centuries 1 decade 2 years 3 months 3 weeks 4 days 1 hour 44 minutes 58 seconds';
```
Output:
```
ans =
6.69 Gseconds
```
]