Using views simplifies the queries, so use something like
create view in_gate_times as
select date(date_time) xdate, time(date_time) xtime
from gate_times where gate_op = 'check-in';
create view out_gate_times as
select date(date_time) xdate, time(date_time) xtime
from gate_times where gate_op = 'check-out';
and then use following query
select i.xdate, i.xtime, ifnull(o.xtime, 'missing')
from in_gate_times i
left join out_gate_times o on i.xdate = o.xdate
union
select o.xdate, ifnull(i.xtime, 'missing'), o.xtime
from in_gate_times i
right join out_gate_times o on i.xdate = o.xdate
order by 1, 2, 3
Check it on SQLFiddle
If using union
made your query slow, use union all
with following change
select i.xdate, i.xtime, ifnull(o.xtime, 'missing')
from in_gate_times i
left join out_gate_times o on i.xdate = o.xdate
union all
select o.xdate, ifnull(i.xtime, 'missing'), o.xtime
from in_gate_times i
right join out_gate_times o on i.xdate = o.xdate
where i.xdate is null
order by 1, 2, 3
check this on SQLFiddle
If views are forbidden just replace each view with its query, so the last query will be
select i.xdate, i.xtime, ifnull(o.xtime, 'missing')
from (select date(date_time) xdate, time(date_time) xtime from gate_times where gate_op = 'check-in') i
left join (select date(date_time) xdate, time(date_time) xtime from gate_times where gate_op = 'check-out') o
on i.xdate = o.xdate
union all
select o.xdate, ifnull(i.xtime, 'missing'), o.xtime
from (select date(date_time) xdate, time(date_time) xtime from gate_times where gate_op = 'check-in') i
right join (select date(date_time) xdate, time(date_time) xtime from gate_times where gate_op = 'check-out') o
on i.xdate = o.xdate
where i.xdate is null
order by 1, 2, 3
It can be checked on SQLFiddle