Change the Timezone

20

2

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.

Beta Decay

Posted 2016-09-11T09:26:52.290

Reputation: 21 478

What about TimeSpan/Duration methods/classes? I assume those are also excluded – pinkfloydx33 – 2016-09-11T09:34:34.977

Also will input values always be valid times? Ie 26:02 and 08:74 would not appear? Same for the UTC offsets? – pinkfloydx33 – 2016-09-11T09:37:33.720

@pinkfloydx33 1) Yes, all of those excluded. 2) Assume all input is valid – Beta Decay – 2016-09-11T09:41:50.010

Do we have to pad the output with zeroes? (eg. Can the last test case output 2:25) – Loovjo – 2016-09-11T09:42:22.327

@Loovjo No, the output does no have to be padded – Beta Decay – 2016-09-11T09:43:25.187

24:54 or 00:54? Also is UTC+14:00 a valid input? – betseg – 2016-09-11T09:50:38.383

Shouldn't the second test case be 15:27? – Loovjo – 2016-09-11T09:52:40.050

@betseg 00:24 and I've added a range of acceptable time offsets – Beta Decay – 2016-09-11T10:01:10.980

Please add a test case for MART and/or NST. – Neil – 2016-09-11T10:29:43.397

@Neil May I ask why? Surely the same principle is demonstrated by the Kathmandu time – Beta Decay – 2016-09-11T11:06:22.133

1If 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? – pinkfloydx33 – 2016-09-11T11:29:50.863

Is the time guaranteed to be the first input, or can the inputs be in either order? – Tortoise – 2016-09-11T11:49:07.793

@BetaDecay In case an answer subtracts 3 hours but then and adds 30 minutes by mistake. – Neil – 2016-09-11T12:56:03.963

@Tortoise Post it as a non-competing entrant, if you like :) Just remember to put non-competing in the header – Beta Decay – 2016-09-11T17:02:44.417

Could the input be a single string such as "17:25 UTC+09:00"? – Arnauld – 2016-09-11T17:10:55.360

@Arnauld Your input may be taken in anyway you wish, as long is follows the format given in the question – Beta Decay – 2016-09-11T17:21:48.430

Answers

2

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

Adám

Posted 2016-09-11T09:26:52.290

Reputation: 37 779

3

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"); }

Lynn

Posted 2016-09-11T09:26:52.290

Reputation: 55 648

1How does this work for negative time offsets e.g. UTC-03:30? – Neil – 2016-09-11T10:20:00.767

Oops, I forgot about those, but thankfully, it’s an easy fix. – Lynn – 2016-09-11T10:23:19.227

3

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.

Neil

Posted 2016-09-11T09:26:52.290

Reputation: 95 035

3

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")

Loovjo

Posted 2016-09-11T09:26:52.290

Reputation: 7 357

1Missing leading zeros in formatted output. Should say Python 2 in heading. Could reduce to a one line function with ;. – Jonathan Allan – 2016-09-11T15:51:46.410

@JonathanAllan You don't need padding zeroes,

– Loovjo – 2016-09-11T15:53:37.013

Ah, cool, missed that bit! Thanks – Jonathan Allan – 2016-09-11T16:00:25.753

2

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.

Jonathan Allan

Posted 2016-09-11T09:26:52.290

Reputation: 67 804

2

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!

Womba

Posted 2016-09-11T09:26:52.290

Reputation: 21

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. – Olivier Grégoire – 2016-09-11T18:41:16.033

@OlivierGrégoire huh? Could you elaborate on the second test please! – Womba – 2016-09-11T18:43:28.647

For the Kathmandu test case, you output 14:27 instead of 15:27. – Olivier Grégoire – 2016-09-11T18:44:09.797

@OlivierGrégoire ah good point – Womba – 2016-09-11T18:47:23.120

Or even java.util.function.Function v=Integer::valueOf. Not sure if that would actually save much. – Robert Fraser – 2016-09-11T19:40:43.100

You could also do something tricky like interface V{int a(String s);} then in your function V v=Integer::valurOf, then each valueOf would be reduced to v.a. Not sure if worth it over the Integer i=1 approach – Robert Fraser – 2016-09-11T19:48:52.330

You can replace the four Integer.valueOf(...) to new Long(...) (PS / FYI: Both Integer.decode(...) and new Integer(...) are also shorter than Integer.valueOf(...), and there is also a fourth option to parse String to an integer which is longer: Integer.parseInt(...).) – Kevin Cruijssen – 2016-09-12T08:13:06.950

@KevinCruijssen Integer.decode(String) won't work with values like 09. new Integer(String) is longer if Womba fixes his issues mentioned in comment 1. – Olivier Grégoire – 2016-09-12T17:43:13.140

1

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

cia_rana

Posted 2016-09-11T09:26:52.290

Reputation: 441

1

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

Arnauld

Posted 2016-09-11T09:26:52.290

Reputation: 111 334

0

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 ':'.

Martin Ender

Posted 2016-09-11T09:26:52.290

Reputation: 184 808

0

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.

Martin Ender

Posted 2016-09-11T09:26:52.290

Reputation: 184 808

0

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}";}

pinkfloydx33

Posted 2016-09-11T09:26:52.290

Reputation: 308

0

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:]","")

Olivier Grégoire

Posted 2016-09-11T09:26:52.290

Reputation: 10 647