DF = DF:lower; -- normalize to lower case
if not cfg.df_vals[DF] then
return error_msg ('bad_format', DF);
end  
if is_set (args._TEST_TIME_) then -- typically used to test the code at a specific utc time
local test_time = get_test_time (args._TEST_TIME_);
if not test_time then
return error_msg ('test_time');
end  
utc_timestamp = os.time(test_time);
else
utc_timestamp = os.time ; -- get current server time (UTC)
end
utc_offset = get_utc_offset ; -- utc offset for specified timezone in seconds
timestamp = utc_timestamp + utc_offset; -- make local time timestamp  
if 'always' == DST then -- if needed to always display dst time
timestamp = timestamp + 3600; -- add a hour for dst
tz_abbr = tz.dst_abbr; -- dst abbreviation
elseif not yesno(DST) then -- for timezones that DO observe dst but for this location ...
tz_abbr = tz.abbr; -- ... dst is not observed (|dst=no) show time as standard time
else
if is_set (tz.dst_begins) and is_set (tz.dst_ends) and is_set (tz.dst_time) then -- make sure we have all of the parts
dst_begin_ts, dst_end_ts, invert = make_dst_timestamps (timestamp); -- get begin and end dst timestamps and invert flag  
if nil == dst_begin_ts or nil == dst_end_ts then
return error_msg ('bad_dst');
end  
if invert then -- southern hemisphere; use beginning and ending of standard time in the comparison
if utc_timestamp >= dst_end_ts and utc_timestamp < dst_begin_ts then -- is current date time standard time?
tz_abbr = tz.abbr; -- standard time abbreviation
else
timestamp = timestamp + 3600; -- add an hour
tz_abbr = tz.dst_abbr; -- dst abbreviation
end
else -- northern hemisphere
if utc_timestamp >= dst_begin_ts and utc_timestamp < dst_end_ts then -- all timestamps are UTC
timestamp = timestamp + 3600; -- add an hour
tz_abbr = tz.dst_abbr;
else
tz_abbr = tz.abbr;
end
end
elseif is_set (tz.dst_begins) or is_set (tz.dst_ends) or is_set (tz.dst_time) then -- if some but not all not all parts then emit error message
return error_msg ('bad_def', args[1]:upper);
else
tz_abbr = tz.abbr; -- dst not observed for this timezone
end
end  
if Dateonly then
if 'iso' == DF then -- |df=iso
DF = 'iso_date';
elseif DF:find ('^dmy') or 'y' == DF then -- |df=dmy, |df=dmy12, |df=dmy24, |df=y
DF = 'dmy_date';
else
DF = 'mdy_date'; -- default
end  
elseif Timeonly or DF:match ('^%d+$') then -- time only of |df= is just digits
DF = table.concat ({'t', DF:match ('%l*(12)') or '24'}); -- |df=12, |df=24, |df=dmy12, |df=dmy24, |df=mdy12, |df=mdy24; default to t24  
elseif 'y' == DF or 'dmy24' == DF then
DF = 'dmy';  
elseif 'mdy24' == DF then
DF = 'mdy';
end  
local dformat;
if is_set (DF_cust) then
dformat=DF_cust;
elseif is_set (DF_cust_a) then -- custom format is am/pm sensitive?
if 'am' == os.date ('%P', timestamp) then -- if current time is am
dformat = DF_cust_a; -- use custom am format
else
dformat = DF_cust_p; -- use custom pm format
end
else
dformat = cfg.format[DF]; -- use format from tables or from |df=
end  
time_string = :callParserFunction ({name='#time', args={dformat, '@'..timestamp, Lang}});
if Lang then
time_string = table.concat ({ -- bidirectional isolation of non-local language; yeah, rather brute force but simple
'<bdi lang="', -- start of opening bdi tag
Lang, -- insert rendered language code
'">', -- end of opening tag
time_string, -- insert the time string
'</bdi>' -- and close the tag
});
end  
if not is_set (tz.article) then -- if some but not all not all parts then emit error message
return error_msg ('bad_def', args[1]:upper);
end  
local refresh_link = (Hide_refresh and '') or
table.concat ({
' <span>[[', -- open span
mw.title.getCurrentTitle:fullUrl({action = 'purge'}), -- add the a refresh link url
' ',
cfg['refresh-label'], -- add the label
']]</span>', -- close the span
});  
local tz_tag = (Hide_tz and '') or
((Unlink_tz and table.concat ({' ', tz_abbr})) or -- unlinked
table.concat ({' ', tz_abbr, ''})); -- linked  
return table.concat ({time_string, tz_tag, refresh_link});  
end  
----------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------  
return {time = time}