Skip to content

Commit

Permalink
Change jerry_port interface to allow for a correct implementation of …
Browse files Browse the repository at this point in the history
…timezones.

The previous jerry_port interface did not allow timezones to be handled correctly,
even if the host system was up to the task. This PR changes the jerry_port interface
to allow a completely correct implementation to exist, and provides one (for Linux/BSD
systems) in default-date.c.

Fixes jerryscript-project#1661

JerryScript-DCO-1.0-Signed-off-by: crazy2be [email protected]
  • Loading branch information
crazy2be committed Sep 26, 2018
1 parent 35fbcd1 commit 3b56d5c
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 172 deletions.
55 changes: 23 additions & 32 deletions docs/05.PORT-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,27 +76,25 @@ void jerry_port_log (jerry_log_level_t level, const char *fmt, ...);
```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 timezone 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 timezone.
*
* 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 js_time_ms The timestamp we want an offset for (could be now, in
* the future, or in the past)
* @param is_utc Is the given timestamp in UTC time? If false, it is in local
time.
*
* @return offset in milliseconds, if available
*. 0 if not available / we are in UTC.
*/
bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p);
bool jerry_port_get_local_tza (double js_time_ms, bool is_utc);
/**
* Get system time
Expand Down Expand Up @@ -198,27 +196,20 @@ jerry_port_log (jerry_log_level_t level, /**< log level */
#include "jerryscript-port.h"

/**
* Default implementation of jerry_port_get_time_zone.
* Default implementation of jerry_port_get_local_tza.
*/
bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p)
double jerry_port_get_local_tza (double unix_ms, /**< ms since unix epoch */
bool is_utc) /**< is the time above in utc? */
{
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)
{
return false;
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);
}

tz_p->offset = tz.tz_minuteswest;
tz_p->daylight_saving_time = tz.tz_dsttime > 0 ? 1 : 0;

return true;
} /* jerry_port_get_time_zone */
return tm.tm_gmtoff * 1000;
} /* jerry_port_get_local_tza */

/**
* Default implementation of jerry_port_get_current_time.
Expand Down
56 changes: 2 additions & 54 deletions jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,41 +301,6 @@ ecma_date_week_day (ecma_number_t time) /**< time value */
return (week_day < 0) ? (7 + week_day) : week_day;
} /* ecma_date_week_day */

/**
* Helper function to get local time zone adjustment.
*
* See also:
* ECMA-262 v5, 15.9.1.7
*
* @return local time zone adjustment
*/
static inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
ecma_date_local_tza (jerry_time_zone_t *tz) /**< time zone information */
{
return tz->offset * -ECMA_DATE_MS_PER_MINUTE;
} /* ecma_date_local_tza */

/**
* Helper function to get the daylight saving time adjustment.
*
* See also:
* ECMA-262 v5, 15.9.1.8
*
* @return daylight saving time adjustment
*/
static inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
ecma_date_daylight_saving_ta (jerry_time_zone_t *tz, /**< time zone information */
ecma_number_t time) /**< time value */
{
JERRY_ASSERT (!ecma_number_is_nan (time));

/*
* TODO: Fix daylight saving calculation.
* https://github.com/jerryscript-project/jerryscript/issues/1661
*/
return tz->daylight_saving_time * ECMA_DATE_MS_PER_HOUR;
} /* ecma_date_daylight_saving_ta */

/**
* Helper function to get local time from UTC.
*
Expand All @@ -347,15 +312,7 @@ ecma_date_daylight_saving_ta (jerry_time_zone_t *tz, /**< time zone information
inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
ecma_date_local_time_zone (ecma_number_t time) /**< time value */
{
jerry_time_zone_t tz;

if (ecma_number_is_nan (time)
|| !jerry_port_get_time_zone (&tz))
{
return ecma_number_make_nan ();
}

return ecma_date_local_tza (&tz) + ecma_date_daylight_saving_ta (&tz, time);
return jerry_port_get_local_tza (time, true);
} /* ecma_date_local_time_zone */

/**
Expand All @@ -369,16 +326,7 @@ ecma_date_local_time_zone (ecma_number_t time) /**< time value */
ecma_number_t
ecma_date_utc (ecma_number_t time) /**< time value */
{
jerry_time_zone_t tz;

if (ecma_number_is_nan (time)
|| !jerry_port_get_time_zone (&tz))
{
return ecma_number_make_nan ();
}

ecma_number_t simple_utc_time = time - ecma_date_local_tza (&tz);
return simple_utc_time - ecma_date_daylight_saving_ta (&tz, simple_utc_time);
return time - jerry_port_get_local_tza (time, false);
} /* ecma_date_utc */

/**
Expand Down
24 changes: 8 additions & 16 deletions jerry-core/include/jerryscript-port.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,27 +111,19 @@ 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 timezone adjustment, in milliseconds. This value, added to a timestamp in UTC
* time, should yield local time. Ideally, this function should satisfy the stipulations
* applied to LocalTZA in section 20.3.1.7 of ecmascript version 9.0 [1].
* [1] https://www.ecma-international.org/ecma-262/9.0/#sec-local-time-zone-adjustment
*
* Note:
* This port function is called by jerry-core when
* CONFIG_DISABLE_DATE_BUILTIN is _not_ defined. Otherwise this function is
* not used.
* 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
* @return milliseconds between local time and utc for the given timestamp.
*/
bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p);
double jerry_port_get_local_tza (double js_time_ms, bool is_utc);

/**
* Get system time
Expand Down
38 changes: 18 additions & 20 deletions jerry-port/default/default-date.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,38 @@
*/

#ifdef __GNUC__
#include <time.h>
#include <sys/time.h>
#endif

#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_tza. 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 localtime at the given unix timestamp, if
* available. 0 otherwise.
*/
bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p) /**< [out] time zone structure to fill */
double jerry_port_get_local_tza (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)
struct tm tm;
time_t now = (time_t)(unix_ms / 1000);
localtime_r (&now, &tm);
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);
}
return ((double)tm.tm_gmtoff) * 1000;
#else
return 0.0;
#endif /* __GNUC__ */

return false;
} /* jerry_port_get_time_zone */
} /* jerry_port_get_local_tza */

/**
* Default implementation of jerry_port_get_current_time. Uses 'gettimeofday' if
Expand Down
11 changes: 4 additions & 7 deletions targets/curie_bsp/source/curie-bsp-port.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,13 @@ void jerry_port_fatal (jerry_fatal_code_t code)
} /* jerry_port_fatal */

/**
* Curie BSP implementation of jerry_port_get_time_zone.
* Curie BSP implementation of jerry_port_get_local_tza.
*/
bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p)
double jerry_port_get_local_tza (double js_time_ms, bool is_utc)
{
//EMPTY implementation
tz_p->offset = 0;
tz_p->daylight_saving_time = 0;

return true;
} /* jerry_port_get_time_zone */
return 0;
} /* jerry_port_get_local_tza */

/**
* Curie BSP implementation of jerry_port_get_current_time.
Expand Down
13 changes: 5 additions & 8 deletions targets/esp8266/user/jerry_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,11 @@ jerry_port_get_current_time (void)
/**
* Dummy function to get the time zone.
*
* @return true
* @return 0, no time zone.
*/
bool
jerry_port_get_time_zone (jerry_time_zone_t *tz_p)
double
jerry_port_get_local_tza (double js_time_ms, bool is_utc)
{
/* We live in UTC. */
tz_p->offset = 0;
tz_p->daylight_saving_time = 0;

return true;
} /* jerry_port_get_time_zone */
return 0;
} /* jerry_port_get_local_tza */
14 changes: 6 additions & 8 deletions targets/mbedos5/source/jerry_port_mbed.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,15 @@ jerry_port_log (jerry_log_level_t level, /**< log level */
#endif /* JSMBED_OVERRIDE_JERRY_PORT_LOG */

/**
* Implementation of jerry_port_get_time_zone.
* Implementation of jerry_port_get_local_tza.
*
* @return true - if success
* @return 0, as we live in UTC.
*/
bool
jerry_port_get_time_zone (jerry_time_zone_t *tz_p) /**< timezone pointer */
double
jerry_port_get_local_tza (double js_time_ms, bool is_utc)
{
tz_p->offset = 0;
tz_p->daylight_saving_time = 0;
return true;
} /* jerry_port_get_time_zone */
return 0;
} /* jerry_port_get_local_tza */

/**
* Implementation of jerry_port_get_current_time.
Expand Down
15 changes: 6 additions & 9 deletions targets/nuttx-stm32f4/jerry_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,19 +492,16 @@ jerry_port_log (jerry_log_level_t level, /**< log level */
} /* jerry_port_log */

/**
* Dummy function to get the time zone.
* Dummy function to get the time zone adjustment.
*
* @return true
* @return 0
*/
bool
jerry_port_get_time_zone (jerry_time_zone_t *tz_p)
double
jerry_port_get_local_tza (double js_time_ms, bool is_utc)
{
/* We live in UTC. */
tz_p->offset = 0;
tz_p->daylight_saving_time = 0;

return true;
} /* jerry_port_get_time_zone */
return 0;
} /* jerry_port_get_local_tza */

/**
* Dummy function to get the current time.
Expand Down
15 changes: 6 additions & 9 deletions targets/tizenrt-artik053/apps/jerryscript/jerry_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,19 +474,16 @@ jerry_port_log (jerry_log_level_t level, /**< log level */
} /* jerry_port_log */

/**
* Dummy function to get the time zone.
* Dummy function to get the time zone adjustment.
*
* @return true
* @return 0
*/
bool
jerry_port_get_time_zone (jerry_time_zone_t *tz_p)
double
jerry_port_get_local_tza (double js_time_ms, bool is_utc)
{
/* We live in UTC. */
tz_p->offset = 0;
tz_p->daylight_saving_time = 0;

return true;
} /* jerry_port_get_time_zone */
return 0;
} /* jerry_port_get_local_tza */

/**
* Dummy function to get the current time.
Expand Down
15 changes: 6 additions & 9 deletions targets/zephyr/src/jerry-port.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,16 @@ jerry_port_get_current_time (void)
} /* jerry_port_get_current_time */

/**
* Dummy function to get the time zone.
* Dummy function to get the time zone adjustment.
*
* @return true
* @return 0
*/
bool
jerry_port_get_time_zone (jerry_time_zone_t *tz_p)
double
jerry_port_get_local_tza (double js_time_ms, bool is_utc)
{
/* We live in UTC. */
tz_p->offset = 0;
tz_p->daylight_saving_time = 0;

return true;
} /* jerry_port_get_time_zone */
return 0;
} /* jerry_port_get_local_tza */

/**
* Provide the implementation of jerryx_port_handler_print_char.
Expand Down

0 comments on commit 3b56d5c

Please sign in to comment.