20
\$\begingroup\$

Challenge

Given a time and a timezone as input, output the time in that timezone.

Time

The time will be given in 24 hour format like so:

hh:mm

Where hh is the two digit hour and mm is the two digit minute. Note that the hour and the minute will always be padded with zeroes like so:

06:09

All the times given are at UTC+00:00.

The hours in your output do not have to be padded wih zeroes but your time it must be in 24 hour format

Timezone

The timezone will be given in the following format:

UTC±hh:mm

Where ± is either going to be a + or a - and hh, is the two digit hour and mm is the two digit minute (again, these will be padded with zeroes).

To find the time in that timezone, you either add (if the symbol is +) or subtract (if the symbol is -) the time after the UTC± from the inputted time.

For example, if the input was 24:56 and UTC-02:50, you would subtract 2 hours and 50 minutes from 24:56:

24:56
02:50 -
-----
22:06

The output would be 22:06.

Examples

Chicago

Input:  08:50 and UTC-06:00
Output: 02:50

Kathmandu

Input:  09:42 and UTC+05:45
Output: 15:27

Samoa

Input:  06:42 and UTC+13:00
Output: 19:42

Hawaii

Input:  02:40 and UTC-10:00
Output: 16:40

Note that this has gone to the previous day.

Tokyo

Input:  17:25 and UTC+09:00
Output: 02:25

Note that this has gone to the following day.

Rules

You must not use any built in date functions or libraries.

Assume all input will be valid times and time offsets.

The timezone will be in the range UTC-24:00 to UTC+24:00 inclusive.

In the case of half past midnight, the correct representation should be 00:30, not 24:30.

Winning

The shortest code in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ What about TimeSpan/Duration methods/classes? I assume those are also excluded \$\endgroup\$ – pinkfloydx33 Sep 11 '16 at 9:34
  • \$\begingroup\$ Also will input values always be valid times? Ie 26:02 and 08:74 would not appear? Same for the UTC offsets? \$\endgroup\$ – pinkfloydx33 Sep 11 '16 at 9:37
  • \$\begingroup\$ @pinkfloydx33 1) Yes, all of those excluded. 2) Assume all input is valid \$\endgroup\$ – Beta Decay Sep 11 '16 at 9:41
  • \$\begingroup\$ Do we have to pad the output with zeroes? (eg. Can the last test case output 2:25) \$\endgroup\$ – Loovjo Sep 11 '16 at 9:42
  • 1
    \$\begingroup\$ If the output doesn't need to be padded would a time like 1:5 be valid instead of 1:05? I'd think only the hours shouldn't be padded. Also your example with 24:56 should that not be 00:56 since you've stated a range up to 24:00 and express similar in your half past midnight scenario? \$\endgroup\$ – pinkfloydx33 Sep 11 '16 at 11:29

12 Answers 12

2
\$\begingroup\$

APL (Dyalog APL), 45 bytes

Expression

Takes two strings as right argument.

24 60⊤∘⍎∘⍕('+-'∩⍕),'/',(0 60⊥2⊃':'⎕VFI ¯5∘↑)¨

Try it online!

Explanation

24 60⊤ the number-to-base-a24b60 conversion

of

the evaluation

of

the formatted (i.e. flattened with separating spaces)

('+-'∩⍕) intersection of "+-" and the formatted input (this extracts the plus or minus)

, followed by

(... the following for each of the inputs (the time and the offset)

0 60⊥ the ab60-to-number conversion of

2⊃ the second element of

':'⎕VFI the, using colon as field separator, Verified and Fixed Input of

¯5∘↑ the last five characters ("hh:mm")

Step-by-step on "17:25" and "UTC+09:00"

The left-side expression on the right side data, gives the data of the next line.

                       '17:25' 'UTC+09:00'
                      /     /   \         \
(...)¨ applies the function train to both inputs
                    /     /       \         \
¯5∘↑               '17:25'         'UTC+09:00'
':'⎕VFI            '17:25'         '09:00' 
2⊃            (1 1)(17 25)         (1 1)(9 0)
0 60⊥                17 25         9 0
                      1045         540
                       \  \       / /
This is where ¨ stops, and execution continues on the resulting list
                         \  \   / /
'/',                      1045 540
('+-'∩⍕),             '/' 1045 540
⍕                 '+' '/' 1045 540
⍎                   '+ / 1045 540'
24 60⊤                        1585
                              2 25
\$\endgroup\$
3
\$\begingroup\$

C, 109 bytes

a,b,c;f(char*t,char*z){for(c=0;z[3];t=z+=3)sscanf(t,"%d:%d",&a,&b),c+=b+a*60;printf("%d:%02d",c/60%24,c%60);}

Invoke as follows:

int main() { f("17:25", "UTC+09:00"); }
\$\endgroup\$
  • 1
    \$\begingroup\$ How does this work for negative time offsets e.g. UTC-03:30? \$\endgroup\$ – Neil Sep 11 '16 at 10:20
  • \$\begingroup\$ Oops, I forgot about those, but thankfully, it’s an easy fix. \$\endgroup\$ – Lynn Sep 11 '16 at 10:23
3
\$\begingroup\$

JavaScript (ES6), 101 bytes

(t,z,g=s=>+(s[3]+s[7]+s[8])+s.slice(3,6)*60,m=g('UTC+'+t)+g(z)+1440)=>(m/60%24|0)+':'+(m/10%6|0)+m%10

Would be 121 bytes if I padded the hours.

\$\endgroup\$
3
\$\begingroup\$

Python 2, 129 bytes

def T(t,a):f=[int.__add__,int.__sub__]["-"in a];m=f(int(t[3:5]),int(a[7:9]));print`f(int(t[0:2])+m/60,int(a[4:6]))%24`+":"+`m%60`

Call as T("02:45", "UTC-05:33")

\$\endgroup\$
  • 1
    \$\begingroup\$ Missing leading zeros in formatted output. Should say Python 2 in heading. Could reduce to a one line function with ;. \$\endgroup\$ – Jonathan Allan Sep 11 '16 at 15:51
  • \$\begingroup\$ @JonathanAllan You don't need padding zeroes, \$\endgroup\$ – Loovjo Sep 11 '16 at 15:53
  • \$\begingroup\$ Ah, cool, missed that bit! Thanks \$\endgroup\$ – Jonathan Allan Sep 11 '16 at 16:00
2
\$\begingroup\$

Python 2, 84 bytes

def f(t,z):i=int;r=60*(i(t[:2])+i(z[3:6]))+i(t[3:])+i(z[3]+z[7:]);print r/60%24,r%60

All test cases are at ideone

Output format is space separated, with no leading zeros.

\$\endgroup\$
2
\$\begingroup\$

Java 201 bytes

String T(String t,String z){return(24+Integer.valueOf(t.substring(0,2))+Integer.valueOf((String)z.subSequence(3,6)))%24+":"+(60+Integer.valueOf(t.substring(3,5))+Integer.valueOf(z.substring(7,9)))%60;}

Called as T("12:00", "UTC+02:40")

Unglolfed for the logic,

String T(String t, String z) { 
    int i = (24 + Integer.valueOf(t.substring(0, 2)) + Integer.valueOf((String) z.subSequence(3, 6))) % 24;
    int j = (60 + Integer.valueOf(t.substring(3, 5)) + Integer.valueOf(z.substring(7, 9))) % 60;
    return i + ":" + j;
}

Any help to get it under 200 would be appreciated!

\$\endgroup\$
  • \$\begingroup\$ This is flawed. Doesn't fulfil the 2nd test (where the hour is incremented). Also, to reduce, why do you use subSequence instead of substring? To golf more, declare Integer i=1; and replace all other Integer by i, so you have i.valueOf instead of Integer.valueOf. \$\endgroup\$ – Olivier Grégoire Sep 11 '16 at 18:41
  • \$\begingroup\$ @OlivierGrégoire huh? Could you elaborate on the second test please! \$\endgroup\$ – Womba Sep 11 '16 at 18:43
  • \$\begingroup\$ For the Kathmandu test case, you output 14:27 instead of 15:27. \$\endgroup\$ – Olivier Grégoire Sep 11 '16 at 18:44
  • \$\begingroup\$ @OlivierGrégoire ah good point \$\endgroup\$ – Womba Sep 11 '16 at 18:47
  • \$\begingroup\$ Or even java.util.function.Function v=Integer::valueOf. Not sure if that would actually save much. \$\endgroup\$ – Robert Fraser Sep 11 '16 at 19:40
1
\$\begingroup\$

Ruby, 95 bytes

g=->s{"60*"+s.scan(/\d+/).map(&:to_i)*?+}
f=->t,z{r=eval(g[t]+z[3]+g[z]);print r/60%24,?:,r%60}

Usage

f[gets,gets]

Inputs(example)

08:50
UTC-06:00
\$\endgroup\$
1
\$\begingroup\$

Javascript (ES6), 93 92 bytes

t=>((t=eval(t.replace(/.*?(.)?(..):(..)/g,'$1($2*60+$3)+720')))/60%24|0)+':'+(t/10%6|0)+t%10

Test cases

let f =
t=>((t=eval(t.replace(/.*?(.)?(..):(..)/g,'$1($2*60+$3)+720')))/60%24|0)+':'+(t/10%6|0)+t%10

console.log(f("08:50 UTC-06:00")); //  2:50
console.log(f("09:42 UTC+05:45")); // 15:27
console.log(f("06:42 UTC+13:00")); // 19:42
console.log(f("02:40 UTC-10:00")); // 16:40
console.log(f("17:25 UTC+09:00")); //  2:25

\$\endgroup\$
0
\$\begingroup\$

Java 156 150 149 147 142 bytes

t->z->{Integer H=100,T=H.valueOf(t.replace(":","")),Z=H.valueOf(z.replace(":","").substring(3)),c=(T/H+Z/H+24)*60+T%H+Z%H;return c/60%24+":"+c%60;}

Test cases & ungolfed

import java.util.function.BiFunction;

public class Main {
    public static void main(String[] args) {

        BiFunction<String,String,String> f = (t,z)->{
            Integer H = 100, // Hundred, used several times, shorter as variable
                    T = H.valueOf(t.replace(":","")), // as int (HHMM)
                    Z = H.valueOf(z.replaceAll("[UTC:]","")), // as int (-HHMM)
                    c = (T/H + Z/H + 24) * 60 + T%H + Z%H; // transform into minutes
            return c/60%24+":"+c%60;
        };

        test(f, "08:50", "UTC-06:00", "02:50");
        test(f, "09:42", "UTC+05:45", "15:27");
        test(f, "03:42", "UTC-05:45", "21:57");
        test(f, "06:42", "UTC+13:00", "19:42");
        test(f, "02:40", "UTC-10:00", "16:40");
        test(f, "17:25", "UTC+09:00", "02:25");
    }

    private static void test(BiFunction<String,String,String> f, String time, String zone, String expected) {
        // Padding is allowed. Make sure the padding is skipped for the test, then.
        String result = String.format("%2s:%2s", (Object[])f.apply(time, zone).split(":")).replace(" ","0");
        if (result.equals(expected)) {
            System.out.printf("%s + %s: OK%n", time, zone);
        } else {
            System.out.printf("%s + %s: Expected \"%s\", got \"%s\"%n", time, zone, expected, result);
        }

    }
}

Shavings

  • 150 -> 149: a/H*60+b/H*60 -> (a/H+b/H)*60
  • 149 -> 147: (T/H+Z/H)*60+1440 -> (T/H+Z/H+24)*60.
  • 147 -> 142: z.replace(":","").substring(3) -> z.replaceAll("[UTC:]","")
\$\endgroup\$
0
\$\begingroup\$

C# 214 205 183 Bytes

string f(char[]t,char[]u){int s=~(u[3]-45),z=48,m=(t[3]-z)*10+t[4]-z+((u[7]-z)*10+u[8]-z)*s,h=(t[0]-z)*10+t[1]-z+((u[4]-z)*10+u[5]-z)*s+m/60+(m>>8)+24;return$"{h%24}:{(m+60)%60:D2}";}

205 byte version

string f(string t,string u){Func<string,int>P=int.Parse;var T=t.Split(':');int s=u[3]<45?1:-1,m=P(T[1])+P(u.Substring(7))*s,h=P(T[0])+P($"{u[4]}"+u[5])*s+m/60+(m<0?-1:0)+24;return$"{h%24}:{(m+60)%60:D2}";}

Ungolfed

string f(char[] t, char[] u)
{
    int s = ~(u[3]-45),
        z = 48,
        m = (t[3] - z) * 10 + t[4] - z + ((u[7] - z) * 10 + u[8] - z) * s,
        h = (t[0] - z) * 10 + t[1] - z + ((u[4] - z) * 10 + u[5] - z) * s + m / 60 + (m>>8) + 24;
    return $"{h % 24}:{(m + 60) % 60:D2}";
}

Original 214:

string f(string t,string u){Func<string,int>P=int.Parse;var T=t.Split(':');int h=P(T[0]),m=P(T[1]),s=u[3]<45?1:-1;m+=P(u.Substring(7))*s;h+=P($"{u[4]}"+u[5])*s+m/60+(m<0?-1:0)+24;return$"{h%24:D2}:{(m+60)%60:D2}";}
\$\endgroup\$
0
\$\begingroup\$

CJam, 40 bytes

r{':/60b}:F~r3>(\F\~1440,=60b{s2Te[}%':*

Try it online! (As a test suite.)

Explanation

r           e# Read first input (time).
{':/60b}:F  e# Define a function F, which splits a string around ':' and
            e# treats the two elements as base-60 digits.
~           e# Run that function on the first input.
r3>         e# Read the second input and discard the 'UTC'.
(           e# Pull off the +-.
\F          e# Apply F to the timezone offset.
\~          e# Execute the + or - on the two amounts of minutes.
1440,=      e# Modulo 1440 to fit everything into the 24-hour format.
60b         e# Obtain base 60 digits again.
{s2Te[}%    e# Convert each digit to a string and pad it to 2 decimal digits.
':*         e# Join them with a ':'.
\$\endgroup\$
0
\$\begingroup\$

Retina, 100 bytes

:
59$*:,
+`(\d+):
$1,$1
\d+
$*
T`1`0`-.+
^
1440$*
+`10|\D

1{1440}

^(1{60})*(.*)
$#1:$.2
\b\d\b
0$&

Try it online!

Explanation

:
59$*:,

Replaces each : with 59 of them and a comma as a separator.

+`(\d+):
$1,$1

Repeatedly duplicates the number in front of a :. So the first two stages multiply the hour-value by 60.

\d+
$*

Convert each number to unary.

T`1`0`-.+

If there's a minus sign in the input, then this transliteration stage turns all the 1s after it into 0s. We're basically using 0 as a unary -1 digit here.

^
1440$*

Insert 1440 1s (i.e. a full day). This is to ensure that the time doesn't get negative.

+`10|\D

This repeatedly removes all non-digits (i.e. the space, the UTC, the + or -, as well as all the , we've inserted) and the 10 combination, thereby cancelling positive and negative digits. This basically subtracts the second number from the first if it's negative, or adds it otherwise.

1{1440}

Removes 1440 1s if possible (basically taking the result modulo 1440 to fit it into a single 24 hours).

^(1{60})*(.*)
$#1:$.2

Decompose the number into hours and minutes by matching as many chunks of 60 digits as possible (counting the chunks with $#1) followed by the remaining digits (whose length is counted with $.2).

\b\d\b
0$&

If there are any single digits in the result, prepend a zero.

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