CREATE OR REPLACE FUNCTION gtfs_timestamp(gtfs_time varchar, target_date date)
RETURNS timestamptz AS
$$
BEGIN
    RETURN CASE
        WHEN (date_part('hour'::text, (gtfs_time)::interval) > (23)::double precision) THEN make_timestamptz((date_part('year'::text, (target_date + '1 day'::interval)))::integer, (date_part('month'::text, (target_date + '1 day'::interval)))::integer, (date_part('day'::text, (target_date + '1 day'::interval)))::integer, ((date_part('hour'::text, (gtfs_time)::interval))::integer - 24), (date_part('minute'::text, (gtfs_time)::interval))::integer, date_part('second'::text, (gtfs_time)::interval), 'Europe/Prague'::text)
        ELSE make_timestamptz((date_part('year'::text, target_date))::integer, (date_part('month'::text, target_date))::integer, (date_part('day'::text, target_date))::integer, (date_part('hour'::text, (gtfs_time)::interval))::integer, (date_part('minute'::text, (gtfs_time)::interval))::integer, date_part('second'::text, (gtfs_time)::interval), 'Europe/Prague'::text)
    END;
END;
$$
LANGUAGE plpgsql;

COMMENT ON FUNCTION gtfs_timestamp(gtfs_time varchar, target_date date) IS '
Converts a time string from GTFS feed to a timestamp.
If the GTFS time string represents a time later than 23:59, the timestamp returned will be for the day following the target date, with the hour adjusted accordingly.
Otherwise, the timestamp returned will be for the target date.
';
