Considering the user’s timezone, the query will look like this:
WITH users_timezone AS (
SELECT
user_id,
CASE WHEN utc_offset IS NULL THEN '00:00:00'
ELSE utc_offset END
FROM user_options uo
LEFT JOIN pg_timezone_names pt ON uo.timezone = pt.name
)
SELECT
p.user_id,
current_timestamp granted_at
FROM badge_posts p
INNER JOIN users_timezone ut ON ut.user_id = p.user_id
WHERE (p.created_at+ut.utc_offset)::time BETWEEN '01:00' AND '05:00'
GROUP BY p.user_id
HAVING count(*) >= 100