Skip to content

Commit 4e63df7

Browse files
committed
[Bug 15821] com.livecode.date: Return timezone with "the local date"
Add a 7th element to the List returned by `the local date`, containing the local timezone's offset from GMT in seconds.
1 parent b059154 commit 4e63df7

4 files changed

Lines changed: 110 additions & 18 deletions

File tree

docs/lcb/notes/feature-timezone.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# LiveCode Builder Standard Library
2+
3+
## Date and time
4+
5+
* `the local time` now returns a list with an additional 7th element.
6+
This is the local time zone's offset from UTC, in seconds.

libscript/src/date.mlc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public foreign handler MCDateExecGetLocalDate(out rDateTime as List) returns not
2828
public foreign handler MCDateExecGetUniversalTime(out rSeconds as CDouble) returns nothing binds to "<builtin>"
2929

3030
/*
31-
Summary: The local gregorian date
31+
Summary: The local Gregorian date
3232

3333
Example:
3434
variable tDateTime as List
@@ -38,7 +38,7 @@ Example:
3838
put tDateTime[3] into tDayOfMonth
3939

4040
Description:
41-
Returns the local date as a list of six numeric components. The
41+
Returns the local date as a list of seven numeric components. The
4242
elements of the list are:
4343

4444
* The year
@@ -47,6 +47,7 @@ elements of the list are:
4747
* The hour (0-23)
4848
* The minute (0-59)
4949
* The second (0-59)
50+
* The offset from UTC in seconds
5051

5152
Tags: Date and time
5253
*/

libscript/src/module-date.cpp

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,97 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
2626
# include <windows.h>
2727
#endif
2828

29-
/* Windows doesn't have localtime_r(), but it does have an equivalent
30-
* function with the arguments in the opposite order! */
3129
#if defined(__WINDOWS__)
32-
// AL-2015-0728: [[ Bug 15410 ]] Windows localtime_s returns an errno_t
33-
// so do a bit of gymnastics to make the signature correct.
34-
inline struct tm *localtime_r(const time_t *p_time, struct tm *r_timeinfo)
30+
static bool
31+
MCDateGetLocalTimeInfo(struct tm & r_timeinfo,
32+
long & r_timezone)
3533
{
36-
if (localtime_s(r_timeinfo, p_time) == 0)
37-
return r_timeinfo;
38-
39-
return NULL;
34+
_get_timezone(&t_timezone);
35+
36+
time_t t_now;
37+
time(&t_now);
38+
39+
/* Windows doesn't have localtime_r(), but it does have an equivalent
40+
* function with the arguments in the opposite order! */
41+
if (0 != localtime_s(&r_timeinfo, &t_time))
42+
{
43+
return false;
44+
}
45+
46+
return true;
47+
}
48+
49+
#elif defined(__MAC__) || defined(__IOS__)
50+
static bool
51+
MCDateGetLocalTimeInfo(struct tm & r_timeinfo,
52+
long & r_timezone)
53+
{
54+
time_t t_now;
55+
time(&t_now);
56+
57+
if (NULL == localtime_r(&t_now, &r_timeinfo))
58+
{
59+
return false;
60+
}
61+
62+
r_timezone = r_timeinfo.tm_gmtoff;
63+
64+
return true;
4065
}
66+
67+
#elif defined(__LINUX__) || defined(__ANDROID__) || defined(__EMSCRIPTEN__)
68+
static bool
69+
MCDateGetLocalTimeInfo(struct tm & r_timeinfo,
70+
long & r_timezone)
71+
{
72+
time_t t_now;
73+
time (&t_now);
74+
75+
if (NULL == localtime_r(&t_now, &r_timeinfo))
76+
{
77+
return false;
78+
}
79+
80+
/* FIXME This may be expensive, but is probably required if
81+
* MCDateGetLocalTimeInfo() is to behave properly over summer time
82+
* changes. */
83+
tzset();
84+
r_timezone = timezone;
85+
86+
return true;
87+
}
88+
89+
#else
90+
# error "MCDateGetLocalTimeInfo() not implemented for this platform"
4191
#endif
4292

4393
extern "C" MC_DLLEXPORT_DEF void
4494
MCDateExecGetLocalDate (MCProperListRef & r_datetime)
4595
{
4696
struct tm t_timeinfo;
47-
time_t t_now;
97+
long t_timezone;
4898

49-
time (&t_now);
50-
if (NULL == localtime_r (&t_now, &t_timeinfo))
99+
if (!MCDateGetLocalTimeInfo(t_timeinfo, t_timezone))
100+
{
51101
return;
102+
}
52103

53-
MCAutoNumberRef t_year, t_month, t_day, t_hour, t_minute, t_second;
104+
MCAutoNumberRef t_year, t_month, t_day, t_hour, t_minute, t_second,
105+
t_gmtoff;
54106
if (!(MCNumberCreateWithInteger (t_timeinfo.tm_year, &t_year) &&
55107
MCNumberCreateWithInteger (t_timeinfo.tm_mon, &t_month) &&
56108
MCNumberCreateWithInteger (t_timeinfo.tm_mday, &t_day) &&
57109
MCNumberCreateWithInteger (t_timeinfo.tm_hour, &t_hour) &&
58110
MCNumberCreateWithInteger (t_timeinfo.tm_min, &t_minute) &&
59-
MCNumberCreateWithInteger (t_timeinfo.tm_sec, &t_second)))
111+
MCNumberCreateWithInteger (t_timeinfo.tm_sec, &t_second) &&
112+
MCNumberCreateWithInteger (t_timezone, &t_gmtoff)))
60113
return;
61114

62115
const MCValueRef t_elements[] = {*t_year, *t_month, *t_day,
63-
*t_hour, *t_minute, *t_second};
116+
*t_hour, *t_minute, *t_second,
117+
*t_gmtoff};
64118

65-
if (!MCProperListCreate (t_elements, 6, r_datetime))
119+
if (!MCProperListCreate (t_elements, 7, r_datetime))
66120
return;
67121
}
68122

tests/lcb/stdlib/date.lcb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Copyright (C) 2015 LiveCode Ltd.
3+
4+
This file is part of LiveCode.
5+
6+
LiveCode is free software; you can redistribute it and/or modify it under
7+
the terms of the GNU General Public License v3 as published by the Free
8+
Software Foundation.
9+
10+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
11+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
17+
18+
module com.livecode.date.tests
19+
20+
public handler TestLocalDate()
21+
variable tDate
22+
put the local date into tDate
23+
test "local date element count" when the number of elements in tDate is 7
24+
test "local date month range" when tDate[2] >= 1 and tDate[2] <= 12
25+
test "local date day range" when tDate[3] >= 1 and tDate[3] <= 31
26+
test "local date hour range" when tDate[4] >= 0 and tDate[4] <= 23
27+
test "local date minute range" when tDate[5] >= 0 and tDate[5] <= 59
28+
test "local date second range" when tDate[6] >= 0 and tDate[6] <= 59
29+
end handler
30+
31+
end module

0 commit comments

Comments
 (0)