added: winix functions: locale, timezone
changed: time zones -- now we have the daylight saving time
different for each year (start, end)
added: config option: time_zone_id (size_t)
time zone identifier for not logged users
or for newly created accounts
those identifiers you can see in etc/time_zones.conf file
or by using timezone winix function with 'a' parameter (timezone/a) (!!IMPROVE ME NOT IMPLEMENTED YET)
default: 34 (Coordinated Universal Time UTC+00:00)
added: config option: locale_default_id (size_t)
locale for not logged users
or for newly created accounts
added: config option: locale_max_id (size_t)
a maximum value of a locale identifier
default: 100 (maximum: 1000)
each locale files should have its own identifier (in "winix_locale_id" field)
from zero to this value
added: config option: time_zone_max_id (size_t)
maximum value of a time zone identifier
time zones with an id greater than this will be skipped
default: 130 (maximum: 1000)
removed: config option: locale_default
git-svn-id: svn://ttmath.org/publicrep/winix/trunk@852 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
@@ -8,6 +8,61 @@
|
||||
*/
|
||||
|
||||
#include "timezone.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
|
||||
|
||||
TimeZone::Dst::Dst()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void TimeZone::Dst::Clear()
|
||||
{
|
||||
has_dst = false;
|
||||
start.Clear();
|
||||
end.Clear();
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
bool TimeZone::Dst::IsDstUsed(const PT::Date & date) const
|
||||
{
|
||||
if( !has_dst )
|
||||
return false;
|
||||
|
||||
if( Compare(start, date) <= 0 ) // !! CHECK ME <= or < ? (what about the one second?)
|
||||
if( Compare(date, end) < 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int TimeZone::Dst::Compare(const PT::Date & date1, const PT::Date & date2) const
|
||||
{
|
||||
// year is ignored
|
||||
|
||||
if( date1.month != date2.month )
|
||||
return date1.month - date2.month;
|
||||
|
||||
if( date1.day != date2.day )
|
||||
return date1.day - date2.day;
|
||||
|
||||
if( date1.hour != date2.hour )
|
||||
return date1.hour - date2.hour;
|
||||
|
||||
if( date1.min != date2.min )
|
||||
return date1.min - date2.min;
|
||||
|
||||
if( date1.sec != date2.sec )
|
||||
return date1.sec - date2.sec;
|
||||
|
||||
// dates are equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,37 +77,45 @@ TimeZone::TimeZone()
|
||||
|
||||
void TimeZone::Clear()
|
||||
{
|
||||
tz_id = -1;
|
||||
tz_offset = 0;
|
||||
tz_has_dst = false;
|
||||
tz_dst_offset = 0;
|
||||
tz_dst_start.Clear();
|
||||
tz_dst_end.Clear();
|
||||
name.clear();
|
||||
id = 0;
|
||||
offset = 0;
|
||||
dst_map.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
TimeZone::Dst * TimeZone::FindDst(int year)
|
||||
{
|
||||
if( dst_map.empty() )
|
||||
return 0;
|
||||
|
||||
DstMap::iterator i = dst_map.lower_bound(year);
|
||||
|
||||
if( i == dst_map.begin() && i->first > year )
|
||||
return 0;
|
||||
|
||||
if( i == dst_map.end() )
|
||||
return &(--i)->second;
|
||||
|
||||
if( i != dst_map.begin() && i->first > year )
|
||||
return &(--i)->second;
|
||||
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t TimeZone::CalcLocalOffset(const PT::Date & utc_date)
|
||||
{
|
||||
time_t offset;
|
||||
time_t dst_offset = 0;
|
||||
|
||||
offset = tz_offset;
|
||||
Dst * dst = FindDst(utc_date.year);
|
||||
|
||||
// !! CHECK ME need to be tested
|
||||
if( dst && dst->IsDstUsed(utc_date) )
|
||||
dst_offset = dst->offset;
|
||||
|
||||
if( tz_has_dst )
|
||||
{
|
||||
PT::Date local(utc_date);
|
||||
|
||||
local += tz_offset;
|
||||
local.year = tz_dst_start.year;
|
||||
tz_dst_end.year = tz_dst_start.year;
|
||||
|
||||
if( tz_dst_start <= local && local < tz_dst_end )
|
||||
offset += tz_dst_offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
return offset + dst_offset;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,27 +139,25 @@ return local;
|
||||
|
||||
time_t TimeZone::CalcUTCOffset(const PT::Date & local_date)
|
||||
{
|
||||
time_t offset;
|
||||
time_t dst_offset = 0;
|
||||
|
||||
offset = tz_offset;
|
||||
Dst * dst = FindDst(local_date.year);
|
||||
|
||||
if( tz_has_dst )
|
||||
if( dst && dst->has_dst )
|
||||
{
|
||||
// !! CHECK ME need to be tested
|
||||
// dst date ranges we have in UTC
|
||||
PT::Date utc(local_date);
|
||||
utc -= (offset + dst->offset);
|
||||
|
||||
PT::Date local(local_date);
|
||||
local -= tz_dst_offset;
|
||||
local.year = tz_dst_start.year;
|
||||
tz_dst_end.year = tz_dst_start.year;
|
||||
|
||||
if( tz_dst_start <= local && local < tz_dst_end )
|
||||
offset += tz_dst_offset;
|
||||
if( dst->IsDstUsed(utc) )
|
||||
dst_offset = dst->offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
return offset + dst_offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t TimeZone::ToUTC(time_t local_time)
|
||||
{
|
||||
time_t offset = CalcUTCOffset(PT::Date(local_time));
|
||||
@@ -119,47 +180,110 @@ return utc;
|
||||
|
||||
|
||||
|
||||
bool TimeZone::SetTz(PT::Space & space)
|
||||
time_t TimeZone::ParseStrOffset(const wchar_t * str)
|
||||
{
|
||||
bool result = true;
|
||||
PT::Date date;
|
||||
bool is_sign = false;
|
||||
time_t offset = 0;
|
||||
|
||||
tz_id = space.Int(L"tz_id", -1);
|
||||
tz_offset = space.Long(L"tz_offset", 0);
|
||||
tz_has_dst = space.Bool(L"tz_has_dst", false);
|
||||
str = SkipWhite(str);
|
||||
|
||||
time_t h13 = 60 * 60 * 13; // 13 hours
|
||||
time_t h15 = 60 * 60 * 15; // 15 hours
|
||||
time_t h24 = 60 * 60 * 24; // 24 hours
|
||||
|
||||
if( tz_offset < -h13 || tz_offset > h15 )
|
||||
result = false;
|
||||
|
||||
if( tz_has_dst )
|
||||
if( *str == '-' )
|
||||
{
|
||||
tz_dst_start.year = 1970;
|
||||
tz_dst_end.year = 1970;
|
||||
|
||||
if( !tz_dst_start.ParseMonthDayTime(space.Text(L"tz_dst_start")) )
|
||||
result = false;
|
||||
|
||||
if( !tz_dst_end.ParseMonthDayTime(space.Text(L"tz_dst_end")) )
|
||||
result = false;
|
||||
|
||||
tz_dst_offset = space.Long(L"tz_dst_offset");
|
||||
|
||||
if( tz_dst_offset < -h24 || tz_dst_offset > h24 )
|
||||
result = false;
|
||||
is_sign = true;
|
||||
str += 1;
|
||||
}
|
||||
else
|
||||
if( *str == '+' )
|
||||
{
|
||||
tz_dst_start.Clear();
|
||||
tz_dst_end.Clear();
|
||||
tz_dst_offset = 0;
|
||||
str += 1;
|
||||
}
|
||||
|
||||
if( !result )
|
||||
Clear();
|
||||
if( date.ParseTime(str) )
|
||||
{
|
||||
offset = date.hour * 60 * 60 + date.min * 60 + date.sec;
|
||||
|
||||
if( is_sign )
|
||||
offset = -offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
time_t TimeZone::GetOffset(PT::Space & space)
|
||||
{
|
||||
std::wstring * offset_str = space.GetValue(L"offset_str");
|
||||
|
||||
if( offset_str )
|
||||
return ParseStrOffset(offset_str->c_str());
|
||||
|
||||
return space.Long(L"offset");
|
||||
}
|
||||
|
||||
|
||||
bool TimeZone::SetTzDst(PT::Space & year)
|
||||
{
|
||||
time_t h24 = 60 * 60 * 24; // 24 hours
|
||||
bool result = true;
|
||||
Dst dst;
|
||||
|
||||
int year_int = Toi(year.name);
|
||||
|
||||
if( year_int < 1970 && year_int > 10000 )
|
||||
return false;
|
||||
|
||||
dst.has_dst = year.Bool(L"has_dst", false);
|
||||
|
||||
if( dst.has_dst )
|
||||
{
|
||||
dst.start.year = year_int;
|
||||
dst.end.year = year_int;
|
||||
|
||||
if( !dst.start.ParseMonthDayTime(year.Text(L"start")) )
|
||||
result = false;
|
||||
|
||||
if( !dst.end.ParseMonthDayTime(year.Text(L"end")) )
|
||||
result = false;
|
||||
|
||||
dst.offset = GetOffset(year);
|
||||
|
||||
if( dst.offset < -h24 || dst.offset > h24 )
|
||||
result = false;
|
||||
}
|
||||
|
||||
if( result )
|
||||
dst_map[year_int] = dst;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool TimeZone::SetTz(PT::Space & space)
|
||||
{
|
||||
bool result = true;
|
||||
name = space.name;
|
||||
id = space.Int(L"id", -1);
|
||||
offset = GetOffset(space);
|
||||
time_t h24 = 60 * 60 * 24; // 24 hours
|
||||
|
||||
if( offset < -h24 || offset > h24 )
|
||||
result = false;
|
||||
|
||||
PT::Space & dst = space.FindAddSpace(L"dst");
|
||||
|
||||
for(size_t i=0 ; i<dst.spaces.size() ; ++i)
|
||||
{
|
||||
PT::Space & year = *dst.spaces[i];
|
||||
|
||||
if( !SetTzDst(year) )
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user