How can I maintain a "virtual column" which is composed of data from 2 tables?
You probably want to store event dates as TIMESTAMP WITH TIME ZONE because just the HH:mm:ss+TZ time without the corresponding date might be ambiguous or misleading -- for example, America/New_York timezone points to two different times during the summer and the winter due to daylight saving changes. Same goes for times that you query against (12:00):

CREATE TABLE users (
    id SERIAL PRIMARY KEY NOT NULL,
    name VARCHAR NOT NULL,
    timezone VARCHAR NOT NULL
);

CREATE TABLE events (
    id SERIAL PRIMARY KEY NOT NULL,
    user_id INT NOT NULL REFERENCES users (id) ON DELETE CASCADE,
    start_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
    end_timestamp TIMESTAMP WITH TIME ZONE NOT NULL
);

CREATE INDEX events_start_timestamp ON events (start_timestamp);
CREATE INDEX events_end_timestamp ON events (end_timestamp);

INSERT INTO users (name, timezone) VALUES
    ('Linas', 'GMT+2');
INSERT INTO events (user_id, start_timestamp, end_timestamp) VALUES
    (1, '2018-02-27 12:00:00-03', '2018-02-27 15:00:00-03');


With that in place, one can query against precalculated timestamps pretty easily (correct timezone conversion will be done behind the scenes by the database itself) and convert the resulting timestamp to user's timezone too:

SELECT users.id,
       users.name,
       (events.start_timestamp::TIMESTAMP AT TIME ZONE users.timezone) AS user_start_timestamp
FROM events
    INNER JOIN users ON events.user_id = users.id
WHERE start_timestamp &gt;= '2018-02-27 11:00:00-03'::TIMESTAMP WITH TIME ZONE
  AND end_timestamp &lt; '2018-02-27 16:00:00-03'::TIMESTAMP WITH TIME ZONE;


(SQL Fiddle)