-
Notifications
You must be signed in to change notification settings - Fork 686
Change jerry_port interface to allow for a correct implementation of timezones. #2540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -111,27 +111,37 @@ void JERRY_ATTR_FORMAT (printf, 2, 3) jerry_port_log (jerry_log_level_t level, c | |
| */ | ||
|
|
||
| /** | ||
| * Jerry time zone structure | ||
| */ | ||
| typedef struct | ||
| { | ||
| int offset; /**< minutes from west */ | ||
| int daylight_saving_time; /**< daylight saving time (1 - DST applies, 0 - not on DST) */ | ||
| } jerry_time_zone_t; | ||
|
|
||
| /** | ||
| * Get timezone and daylight saving data | ||
| * Get local time zone adjustment, in milliseconds, for the given timestamp. | ||
| * The timestamp can be specified in either UTC or local time, depending on | ||
| * the value of is_utc. Adding the value returned from this function to | ||
| * a timestamp in UTC time should result in local time for the current time | ||
| * zone, and subtracting it from a timestamp in local time should result in | ||
| * UTC time. | ||
| * | ||
| * Ideally, this function should satisfy the stipulations applied to LocalTZA | ||
| * in section 20.3.1.7 of the ECMAScript version 9.0 spec. | ||
| * | ||
| * See Also: | ||
| * ECMA-262 v9, 20.3.1.7 | ||
| * | ||
| * Note: | ||
| * This port function is called by jerry-core when | ||
| * CONFIG_DISABLE_DATE_BUILTIN is _not_ defined. Otherwise this function is | ||
| * not used. | ||
| * | ||
| * @param[out] tz_p time zone structure to fill. | ||
| * @return true - if success | ||
| * false - otherwise | ||
| * @param unix_ms The unix timestamp we want an offset for, given in | ||
| * millisecond precision (could be now, in the future, | ||
| * or in the past). As with all unix timestamps, 0 refers to | ||
| * 1970-01-01, a day is exactly 86 400 000 milliseconds, and | ||
| * leap seconds cause the same second to occur twice. | ||
| * @param is_utc Is the given timestamp in UTC time? If false, it is in local | ||
| * time. | ||
| * | ||
| * @return milliseconds between local time and UTC for the given timestamp, | ||
| * if available | ||
| *. 0 if not available / we are in UTC. | ||
| */ | ||
| bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p); | ||
| double jerry_port_get_local_time_zone_adjustment (double unix_ms, bool is_utc); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question to other reviewers (again, ping @zherczeg @LaszloLango ): do we want this long identifiers / port API identifiers?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer full words, so I like the current one. |
||
|
|
||
| /** | ||
| * Get system time | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,19 @@ file(GLOB SOURCE_PORT_DEFAULT *.c) | |
| # (should only be necessary if we used compiler default libc but not checking that) | ||
| set(DEFINES_PORT_DEFAULT _BSD_SOURCE _DEFAULT_SOURCE) | ||
|
|
||
| INCLUDE (CheckStructHasMember) | ||
| # CHECK_STRUCT_HAS_MEMBER works by trying to compile some C code that accesses the | ||
| # given field of the given struct. However, our default compiler options break this | ||
| # C code, so turn a couple of them off for this. | ||
| set(CMAKE_REQUIRED_FLAGS "-Wno-error=strict-prototypes -Wno-error=old-style-definition") | ||
| # tm.tm_gmtoff is non-standard, so glibc doesn't expose it in c99 mode | ||
| # (our default). Define some macros to expose it anyway. | ||
| set(CMAKE_REQUIRED_DEFINITIONS "-D_BSD_SOURCE -D_DEFAULT_SOURCE") | ||
| CHECK_STRUCT_HAS_MEMBER ("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) | ||
| if(HAVE_TM_GMTOFF) | ||
| set(DEFINES_PORT_DEFAULT ${DEFINES_PORT_DEFAULT} HAVE_TM_GMTOFF) | ||
| endif() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this only affects the default implementation?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. It also doesn't seem to work, and I haven't been able to figure out why yet. My cmake-fu is not great.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't investigated all the details of the problem but my guess is that the root of the problem is that
So, if
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is something to do with my defines not getting passed. If I put a message() inside the if, it gets printed (at least, if I run #include <stdio.h>
#include <time.h>
#include <stdbool.h>
double jerry_port_get_local_time_zone_adjustment (double unix_ms, /**< ms since unix epoch */
bool is_utc) /**< is the time above in UTC? */
{
struct tm tm;
time_t now = (time_t) (unix_ms / 1000);
localtime_r (&now, &tm);
if (!is_utc)
{
now -= tm.tm_gmtoff;
localtime_r (&now, &tm);
}
return ((double) tm.tm_gmtoff) * 1000;
} /* jerry_port_get_local_time_zone_adjustment */
int main() {
double adj = jerry_port_get_local_time_zone_adjustment(0, 0);
printf("%lf\n", adj);
}(the above compiles without any warnings or errors with just I verified that it isn't trying to use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Confirmed that when running Looking at the two different
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see now what you were saying. I didn't realize jerryscript compiled in strict c99 mode (which, as you said, makes
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huh, so the default source code that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Finally got it all to build. On the plus side, I'm a lot more familiar with cmake now :). |
||
|
|
||
| # Sleep function availability check | ||
| INCLUDE (CheckIncludeFiles) | ||
| CHECK_INCLUDE_FILES (time.h HAVE_TIME_H) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,41 +13,43 @@ | |
| * limitations under the License. | ||
| */ | ||
|
|
||
| #ifdef HAVE_TM_GMTOFF | ||
| #include <time.h> | ||
| #endif /* HAVE_TM_GMTOFF */ | ||
| #ifdef __GNUC__ | ||
| #include <sys/time.h> | ||
| #endif | ||
| #endif /* __GNUC__ */ | ||
|
|
||
| #include "jerryscript-port.h" | ||
| #include "jerryscript-port-default.h" | ||
|
|
||
| /** | ||
| * Default implementation of jerry_port_get_time_zone. Uses 'gettimeofday' if | ||
| * available on the system, does nothing otherwise. | ||
| * Default implementation of jerry_port_get_local_time_zone_adjustment. Uses the 'tm_gmtoff' field | ||
| * of 'struct tm' (a GNU extension) filled by 'localtime_r' if available on the | ||
| * system, does nothing otherwise. | ||
| * | ||
| * @return true - if 'gettimeofday' is available and executed successfully, | ||
| * false - otherwise. | ||
| * @return offset between UTC and local time at the given unix timestamp, if | ||
| * available. Otherwise, returns 0, assuming UTC time. | ||
| */ | ||
| bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p) /**< [out] time zone structure to fill */ | ||
| double jerry_port_get_local_time_zone_adjustment (double unix_ms, /**< ms since unix epoch */ | ||
| bool is_utc) /**< is the time above in UTC? */ | ||
| { | ||
| #ifdef __GNUC__ | ||
| struct timeval tv; | ||
| struct timezone tz; | ||
|
|
||
| /* gettimeofday may not fill tz, so zero-initializing */ | ||
| tz.tz_minuteswest = 0; | ||
| tz.tz_dsttime = 0; | ||
|
|
||
| if (gettimeofday (&tv, &tz) == 0) | ||
| #ifdef HAVE_TM_GMTOFF | ||
| struct tm tm; | ||
| time_t now = (time_t) (unix_ms / 1000); | ||
| localtime_r (&now, &tm); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A little bit of thinking aloud: Another approach could be to use So, it seems to me that we need to rely on at least two extensions to get this work. I'm not sure yet which way to go. (That's why I was thinking aloud. I'm open to inputs.)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
[0] https://linux.die.net/man/3/localtime_r
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please note that we are targeting embedded systems way below the embedded-Linux world as well. And there, it is easy to find missing bits and pieces. E.g., it's a bit hard to dig for info, but it's probable that neither TI's MSP430 C compiler nor the IAR Embedded Workbench have support for That being said, the platforms these compilers compile for will most probably have their own implementation for all/most jerry port functions instead of these default implementations. Still, it's good to keep those ideals (i.e., C99 conformance) in mind that drive the project. For the core engine library, we must be strict, I think. For libraries around it, we might be less strict, provided that the extensions are properly guarded. Here that seems to be the case. Anyway, I'd like to hear the opinion of other reviewers. I summon @zherczeg @LaszloLango
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My point was mainly that if a given platform has
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand correctly this is the default implementation. Low-end targets must have their own implementation (or return 0 if not supported).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Btw what about windows? Does gcc on windows support this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, this is the default implementation. Most embedded targets won't even use this, or they will just use the Windows does not support |
||
| if (!is_utc) | ||
| { | ||
| tz_p->offset = tz.tz_minuteswest; | ||
| tz_p->daylight_saving_time = tz.tz_dsttime > 0 ? 1 : 0; | ||
|
|
||
| return true; | ||
| now -= tm.tm_gmtoff; | ||
| localtime_r (&now, &tm); | ||
| } | ||
| #endif /* __GNUC__ */ | ||
|
|
||
| return false; | ||
| } /* jerry_port_get_time_zone */ | ||
| return ((double) tm.tm_gmtoff) * 1000; | ||
| #else /* !HAVE_TM_GMTOFF */ | ||
| (void) unix_ms; | ||
| (void) is_utc; | ||
| return 0.0; | ||
| #endif /* HAVE_TM_GMTOFF */ | ||
| } /* jerry_port_get_local_time_zone_adjustment */ | ||
|
|
||
| /** | ||
| * Default implementation of jerry_port_get_current_time. Uses 'gettimeofday' if | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.