Author: Stephan <[email protected]>
Branch:
Changeset: r358:0eca2e45608b
Date: 2013-02-19 13:02 +0100
http://bitbucket.org/pypy/lang-js/changeset/0eca2e45608b/
Log: added translatable date and time functions
diff --git a/js/builtins/date.py b/js/builtins/date.py
--- a/js/builtins/date.py
+++ b/js/builtins/date.py
@@ -1,9 +1,16 @@
from rpython.rlib.rfloat import NAN, isnan
-from rpython.rlib.objectmodel import we_are_translated
-import datetime
from js.builtins import get_arg
-from js.object_space import w_return, hide_on_translate, _w
+from js.object_space import w_return, _w
+from js import rtime
+
+fMSEC = 1
+fSEC = 2
+fMIN = 3
+fHOUR = 4
+fDAY = 1
+fMONTH = 2
+fYEAR = 3
def setup(global_object):
@@ -103,14 +110,9 @@
@w_return
def to_string(this, args):
- if not we_are_translated():
- d = w_date_to_datetime(this)
- local = to_local(d)
-
- s = local.strftime('%a %b %d %Y %H:%M:%S GMT%z (%Z)')
- return s
-
- return this.PrimitiveValue().to_string()
+ t = make_jstime(this)
+ s = t.strftime('%a %b %d %Y %H:%M:%S GMT%z (%Z)', local=True)
+ return s
# 15.9.5.8
@@ -127,146 +129,121 @@
# 15.9.5.10
@w_return
-@hide_on_translate(0)
def get_full_year(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.year
+ t = make_jstime(this)
+ return t.year(local=True)
# 15.9.5.11
@w_return
-@hide_on_translate(0)
def get_utc_full_year(this, args):
- d = w_date_to_datetime(this)
- return d.year
+ t = make_jstime(this)
+ return t.year()
# 15.9.5.12
@w_return
-@hide_on_translate(0)
def get_month(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.month
+ t = make_jstime(this)
+ return t.month(local=True)
# 15.9.5.13
@w_return
-@hide_on_translate(0)
def get_utc_month(this, args):
- d = w_date_to_datetime(this)
- return d.day
+ t = make_jstime(this)
+ return t.month()
# 15.9.5.14
@w_return
-@hide_on_translate(0)
def get_date(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.day
+ t = make_jstime(this)
+ return t.day(local=True)
# 15.9.5.15
@w_return
-@hide_on_translate(0)
def get_utc_date(this, args):
- d = w_date_to_datetime(this)
- return d.day
+ t = make_jstime(this)
+ return t.day()
# 15.9.5.16
@w_return
-@hide_on_translate(0)
def get_day(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.weekday()
+ t = make_jstime(this)
+ return t.wday(local=True)
# 15.9.5.17
@w_return
-@hide_on_translate(0)
def get_utc_day(this, args):
- d = w_date_to_datetime(this)
- return d.weekday()
+ t = make_jstime(this)
+ return t.wday()
# 15.9.5.18
@w_return
-@hide_on_translate(0)
def get_hours(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.hour
+ t = make_jstime(this)
+ return t.hour(local=True)
# 15.9.5.19
@w_return
-@hide_on_translate(0)
def get_utc_hours(this, args):
- d = w_date_to_datetime(this)
- return d.hour
+ t = make_jstime(this)
+ return t.hour()
# 15.9.5.20
@w_return
-@hide_on_translate(0)
def get_minutes(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.minute
+ t = make_jstime(this)
+ return t.min(local=True)
# 15.9.5.21
@w_return
-@hide_on_translate(0)
def get_utc_minutes(this, args):
- d = w_date_to_datetime(this)
- return d.minute
+ t = make_jstime(this)
+ return t.min()
# 15.9.5.22
@w_return
-@hide_on_translate(0)
def get_seconds(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.second
+ t = make_jstime(this)
+ return t.sec(local=True)
# 15.9.5.23
@w_return
-@hide_on_translate(0)
def get_utc_seconds(this, args):
- d = w_date_to_datetime(this)
- return d.second
+ t = make_jstime(this)
+ return t.sec()
# 15.9.5.24
@w_return
-@hide_on_translate(0)
def get_milliseconds(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- return local.microsecond / 1000
+ t = make_jstime(this)
+ return t.msec(local=True)
# 15.9.5.25
@w_return
-@hide_on_translate(0)
def get_utc_milliseconds(this, args):
- d = w_date_to_datetime(this)
- return d.microsecond / 1000
+ t = make_jstime(this)
+ return t.msec()
# 15.9.5.26
@w_return
-@hide_on_translate(0)
def get_timezone_offset(this, args):
- d = w_date_to_datetime(this)
- offset = -1 * (d.utcoffset().total_seconds() / 60)
+ t = make_jstime(this)
+ offset = -1 * t.utc_offset() / 60
return offset
@@ -290,154 +267,137 @@
# 15.9.5.28
@w_return
-@hide_on_translate(0)
def set_milliseconds(this, args):
- time_args = to_timeargs(args, 1)
- return set_datetime(this, time_args)
+ time_args = to_timeargs(args, fMSEC)
+ return change_wdate(this, time_args, local=True)
# 15.9.5.29
@w_return
-@hide_on_translate(0)
def set_utc_milliseconds(this, args):
- time_args = to_timeargs(args, 1)
- return set_utc_datetime(this, time_args)
+ time_args = to_timeargs(args, fMSEC)
+ return change_wdate(this, time_args)
# 15.9.5.30
@w_return
-@hide_on_translate(0)
def set_seconds(this, args):
- time_args = to_timeargs(args, 2)
- return set_datetime(this, time_args)
+ time_args = to_timeargs(args, fSEC)
+ return change_wdate(this, time_args, local=True)
# 15.9.5.30
@w_return
-@hide_on_translate(0)
def set_utc_seconds(this, args):
- time_args = to_timeargs(args, 2)
- return set_utc_datetime(this, time_args)
+ time_args = to_timeargs(args, fSEC)
+ return change_wdate(this, time_args)
# 15.9.5.32
@w_return
-@hide_on_translate(0)
def set_minutes(this, args):
- time_args = to_timeargs(args, 3)
- return set_datetime(this, time_args)
+ time_args = to_timeargs(args, fMIN)
+ return change_wdate(this, time_args, local=True)
# 15.9.5.33
@w_return
-@hide_on_translate(0)
def set_utc_minutes(this, args):
- time_args = to_timeargs(args, 3)
- return set_utc_datetime(this, time_args)
+ time_args = to_timeargs(args, fMIN)
+ return change_wdate(this, time_args)
# 15.9.5.34
@w_return
-@hide_on_translate(0)
def set_hours(this, args):
- time_args = to_timeargs(args, 4)
- return set_datetime(this, time_args)
+ time_args = to_timeargs(args, fHOUR)
+ return change_wdate(this, time_args, local=True)
# 15.9.5.35
@w_return
-@hide_on_translate(0)
def set_utc_hours(this, args):
- time_args = to_timeargs(args, 4)
- return set_utc_datetime(this, time_args)
+ time_args = to_timeargs(args, fHOUR)
+ return change_wdate(this, time_args)
# 15.9.5.36
@w_return
-@hide_on_translate(0)
def set_date(this, args):
- date_args = to_dateargs(args, 1)
- return set_datetime(this, date_args)
+ date_args = to_dateargs(args, fDAY)
+ return change_wdate(this, date_args, local=True)
# 15.9.5.37
@w_return
-@hide_on_translate(0)
def set_utc_date(this, args):
- date_args = to_dateargs(args, 1)
- return set_utc_datetime(this, date_args)
+ date_args = to_dateargs(args, fDAY)
+ return change_wdate(this, date_args)
# 15.9.5.38
@w_return
-@hide_on_translate(0)
def set_month(this, args):
- date_args = to_dateargs(args, 2)
- return set_datetime(this, date_args)
+ date_args = to_dateargs(args, fMONTH)
+ return change_wdate(this, date_args, local=True)
# 15.9.5.39
@w_return
-@hide_on_translate(0)
def set_utc_month(this, args):
- date_args = to_dateargs(args, 2)
- return set_utc_datetime(this, date_args)
+ date_args = to_dateargs(args, fMONTH)
+ return change_wdate(this, date_args)
# 15.9.5.38
@w_return
-@hide_on_translate(0)
def set_full_year(this, args):
- date_args = to_dateargs(args, 3)
- return set_datetime(this, date_args)
+ date_args = to_dateargs(args, fYEAR)
+ return change_wdate(this, date_args, local=True)
# 15.9.5.39
@w_return
-@hide_on_translate(0)
def set_utc_full_year(this, args):
- date_args = to_dateargs(args, 3)
- return set_utc_datetime(this, date_args)
+ date_args = to_dateargs(args, fYEAR)
+ return change_wdate(this, date_args)
# B.2.4
@w_return
-@hide_on_translate(0)
def get_year(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- y = local.year - 1900
+ t = make_jstime(this)
+ y = t.year(local=True) - 1900
return y
# B.2.5
@w_return
-@hide_on_translate(0)
def set_year(this, args):
arg0 = get_arg(args, 0)
year = arg0.ToInteger()
if isnan(year) or year < 0 or year > 99:
- this.set_primitive_value(NAN)
+ this.set_primitive_value(_w(NAN))
return NAN
y = year + 1900
-
- return set_datetime(this, [y])
+ c = JsDateChange()
+ c.set_year(y)
+ change_wdate(this, c)
+ return y
# 15.9.5.42
@w_return
-@hide_on_translate(0)
def to_utc_string(this, args):
- d = w_date_to_datetime(this)
- s = d.strftime('%c %z')
+ t = make_jstime(this)
+ s = t.strftime('%c %z')
return s
# B.2.6
@w_return
-@hide_on_translate(0)
def to_gmt_string(this, args):
return to_utc_string(this, args)
@@ -456,105 +416,247 @@
####### helper
-def to_timeargs(args, count):
- a = argv(args)
- rfilled = rfill_args(a, count)
- lfilled = lfill_args(rfilled, 7)
- return lfilled
+def to_timeargs(args, fill):
+ a = w_argi(args)
+ c = JsDateChange()
+ ac = len(a)
+ if fill == fMSEC:
+ c.set_msecond(a[0])
+ elif fill == fSEC:
+ c.set_second(a[0])
+ if ac > 1:
+ c.set_msecond(a[1])
+ elif fill == fMIN:
+ c.set_minute(a[0])
+ if ac > 1:
+ c.set_second(a[1])
+ if ac > 2:
+ c.set_msecond(a[2])
+ elif fill == fHOUR:
+ c.set_hour(a[0])
+ if ac > 1:
+ c.set_minute(a[1])
+ if ac > 2:
+ c.set_second(a[2])
+ if ac > 3:
+ c.set_msecond(a[3])
-def to_dateargs(args, count):
- a = argv(args)
- rfilled = rfill_args(a, count)
- lfilled = lfill_args(rfilled, 3)
- return lfilled
+ return c
-def set_datetime(this, args):
- d = w_date_to_datetime(this)
- local = to_local(d)
- new_d = change_datetime(local, *args)
+def to_dateargs(args, fill):
+ a = w_argi(args)
+ c = JsDateChange()
+ ac = len(a)
- u = datetime_to_msecs(new_d)
- this.set_primitive_value(u)
+ if fill == fDAY:
+ c.set_day(a[0])
+ elif fill == fMONTH:
+ c.set_month(a[0])
+ if ac > 1:
+ c.set_day(a[1])
+ elif fill == fYEAR:
+ c.year = a[0]
+ if ac > 1:
+ c.set_month(a[1])
+ if ac > 2:
+ c.set_day(a[2])
- return u
+ return c
-def set_utc_datetime(this, args):
- d = w_date_to_datetime(this)
- new_d = change_datetime(d, *args)
+class JsDateChange(object):
+ year = 0
+ has_year = False
+ month = 0
+ has_month = False
+ day = 0
+ has_day = False
+ hour = 0
+ has_hour = False
+ minute = 0
+ has_minute = False
+ second = 0
+ has_second = False
+ msecond = 0
+ has_msecond = False
- u = datetime_to_msecs(new_d)
- this.set_primitive_value(u)
+ def set_year(self, year):
+ self.has_year = True
+ self.year = year
- return u
+ def set_month(self, month):
+ self.has_month = True
+ self.month = month
+ def set_day(self, day):
+ self.has_day = True
+ self.day = day
-def argv(args):
- return [arg.ToInteger() for arg in args]
+ def set_hour(self, hour):
+ self.has_hour = True
+ self.hour = hour
+ def set_minute(self, minute):
+ self.has_minute = True
+ self.minute = minute
-def lfill_args(args, count):
- if count > 0:
- missing = count - len(args)
- return ([None] * missing) + args
- return args
+ def set_second(self, second):
+ self.has_second = True
+ self.second = second
+ def set_msecond(self, msecond):
+ self.has_msecond = True
+ self.msecond = msecond
-def rfill_args(args, count):
- if count > 0:
- missing = count - len(args)
- return args + ([None] * missing)
- return args
+def change_wdate(w_date, time_change, local=False):
+ t = make_jstime(w_date)
+ if time_change.has_year:
+ t.set_year(time_change.year, local)
-def change_datetime(d, year=None, month=None, day=None, hour=None,
minute=None, second=None, ms=None):
- args = {}
- if year is not None:
- args['year'] = year
- if month is not None:
- args['month'] = month
- if day is not None:
- args['day'] = day
- if hour is not None:
- args['hour'] = hour
- if minute is not None:
- args['minute'] = minute
- if second is not None:
- args['second'] = second
- if ms is not None:
- mu_sec = ms * 1000
- args['microsecond'] = mu_sec
- return d.replace(**args)
+ if time_change.has_month:
+ t.set_month(time_change.month, local)
+ if time_change.has_day:
+ t.set_day(time_change.day, local)
-def w_date_to_datetime(w_date):
- msecs = w_date.PrimitiveValue().ToInteger()
- return msecs_to_datetime(msecs)
+ if time_change.has_hour:
+ t.set_hour(time_change.hour, local)
+ if time_change.has_minute:
+ t.set_min(time_change.minute, local)
-def msecs_to_datetime(timestamp_msecs):
- from dateutil.tz import tzutc
+ if time_change.has_second:
+ t.set_sec(time_change.second, local)
- seconds_since_epoch = timestamp_msecs / 1000
- msecs = timestamp_msecs - seconds_since_epoch * 1000
- timestamp = seconds_since_epoch + (msecs / 1000.0)
- utc = datetime.datetime.utcfromtimestamp(timestamp)
- utc = utc.replace(tzinfo=tzutc())
+ if time_change.has_msecond:
+ t.set_msec(time_change.msecond, local)
- return utc
+ w_t = _w(t.to_msec_epoc())
+ w_date.set_primitive_value(w_t)
+ return w_t
-def datetime_to_msecs(d):
- from time import mktime
- timestamp = int(mktime(d.utctimetuple()))
- msecs = timestamp * 1000
- msecs += (d.microsecond / 1000)
- return msecs
+def w_argi(args):
+ argi = []
+ for arg in args:
+ a = arg.ToInteger()
+ assert isinstance(a, int)
+ argi += [a]
+ return argi
-def to_local(datetime):
- from dateutil.tz import tzlocal
- return datetime.astimezone(tzlocal())
+
+def _change_tuple(t, idx, value):
+ assert len(t) == 9
+ l = list(t)
+ l[idx] = value
+ return (l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8])
+
+
+def _get_tuple_at(t, idx):
+ l = list(t)
+ return l[idx]
+
+
+class JsTime(object):
+ def __init__(self, msec_timestamp):
+ self._timep = msec_timestamp / 1000
+ self._msec = msec_timestamp - self._timep * 1000
+
+ def __str__(self):
+ return 'JsTime(%d)' % (self.to_msec_epoc(), )
+
+ def _get_time(self, local):
+ if local:
+ return self.localtime()
+ return self.gmtime()
+
+ def gmtime(self):
+ return rtime.gmtime(self._timep)
+
+ def localtime(self):
+ return rtime.localtime(self._timep)
+
+ def _set_time(self, tm, local):
+ if local:
+ self._timep = int(rtime.mktime(tm))
+ else:
+ self._timep = int(rtime.timegm(tm))
+
+ def _update_time(self, component, value, local):
+ tm = self._get_time(local)
+ new_tm = _change_tuple(tm, component, value)
+ self._set_time(new_tm, local)
+
+ def _get_time_component(self, component, local):
+ return _get_tuple_at(self._get_time(local), component)
+
+ def _get_timestamp(self):
+ return self._timep
+
+ def to_msec_epoc(self):
+ return (self._get_timestamp() * 1000) + (self.msec())
+
+ def year(self, local=False):
+ return self._get_time_component(rtime.tmYEAR, local)
+
+ def set_year(self, year, local=False):
+ self._update_time(rtime.tmYEAR, year, local)
+
+ def month(self, local=False):
+ return self._get_time_component(rtime.tmMONTH, local)
+
+ def set_month(self, month, local=False):
+ self._update_time(rtime.tmMONTH, month, local)
+
+ def day(self, local=False):
+ return self._get_time_component(rtime.tmDAY, local)
+
+ def set_day(self, day, local=False):
+ self._update_time(rtime.tmDAY, day, local)
+
+ def hour(self, local=False):
+ return self._get_time_component(rtime.tmHOUR, local)
+
+ def set_hour(self, hour, local=False):
+ self._update_time(rtime.tmHOUR, hour, local)
+
+ def min(self, local=False):
+ return self._get_time_component(rtime.tmMIN, local)
+
+ def set_min(self, min, local=False):
+ self._update_time(rtime.tmMIN, min, local)
+
+ def sec(self, local=False):
+ return self._get_time_component(rtime.tmSEC, local)
+
+ def set_sec(self, sec, local=False):
+ self._update_time(rtime.tmSEC, sec, local)
+
+ def msec(self, local=False):
+ return self._msec
+
+ def set_msec(self, msec, local=False):
+ assert msec < 1000
+ self._msec = msec
+
+ def wday(self, local=False):
+ return self._get_time_component(rtime.tmWDAY, local)
+
+ def strftime(self, format, local=False):
+ tm = self._get_time(local)
+ s = rtime.strftime(format, tm)
+ return s
+
+ def utc_offset(self):
+ o = rtime.mktime(self.localtime()) - rtime.mktime(self.gmtime())
+ return o
+
+
+def make_jstime(w_obj):
+ msecs = w_obj.PrimitiveValue().ToInteger()
+ return JsTime(msecs)
diff --git a/js/rtime.py b/js/rtime.py
new file mode 100644
--- /dev/null
+++ b/js/rtime.py
@@ -0,0 +1,187 @@
+# see pypy/module/rctime/interp_time.py
+import os
+
+from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.rarithmetic import intmask
+from pypy.module.rctime.interp_time import c_gmtime, c_localtime, c_mktime,
glob_buf, _POSIX, _CYGWIN, _WIN, c_tzset, c_strftime
+
+tmYEAR = 0
+tmMONTH = 1
+tmDAY = 2
+tmHOUR = 3
+tmMIN = 4
+tmSEC = 5
+tmWDAY = 6
+
+
+def _tm_to_tuple(t):
+ time_tuple = (
+ rffi.getintfield(t, 'c_tm_year') + 1900,
+ rffi.getintfield(t, 'c_tm_mon') + 1, # want january == 1
+ rffi.getintfield(t, 'c_tm_mday'),
+ rffi.getintfield(t, 'c_tm_hour'),
+ rffi.getintfield(t, 'c_tm_min'),
+ rffi.getintfield(t, 'c_tm_sec'),
+ ((rffi.getintfield(t, 'c_tm_wday') + 6) % 7), # want monday == 0
+ rffi.getintfield(t, 'c_tm_yday') + 1, # want january, 1 == 1
+ rffi.getintfield(t, 'c_tm_isdst'))
+ return time_tuple
+
+
+def _gettmarg(tup):
+ if len(tup) != 9:
+ raise Exception("argument must be sequence of length 9, not %d",
len(tup))
+
+ y = tup[0]
+ tm_mon = tup[1]
+ if tm_mon == 0:
+ tm_mon = 1
+ tm_mday = tup[2]
+ if tm_mday == 0:
+ tm_mday = 1
+ tm_yday = tup[7]
+ if tm_yday == 0:
+ tm_yday = 1
+ rffi.setintfield(glob_buf, 'c_tm_mon', tm_mon)
+ rffi.setintfield(glob_buf, 'c_tm_mday', tm_mday)
+ rffi.setintfield(glob_buf, 'c_tm_hour', tup[3])
+ rffi.setintfield(glob_buf, 'c_tm_min', tup[4])
+ rffi.setintfield(glob_buf, 'c_tm_sec', tup[5])
+ rffi.setintfield(glob_buf, 'c_tm_wday', tup[6])
+ rffi.setintfield(glob_buf, 'c_tm_yday', tm_yday)
+ rffi.setintfield(glob_buf, 'c_tm_isdst', tup[8])
+ if _POSIX:
+ if _CYGWIN:
+ pass
+ else:
+ # actually never happens, but makes annotator happy
+ glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO)
+ rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0)
+
+ if y < 1900:
+ if 69 <= y <= 99:
+ y += 1900
+ elif 0 <= y <= 68:
+ y += 2000
+ else:
+ raise Exception("year out of range")
+
+ # tm_wday does not need checking of its upper-bound since taking "%
+ # 7" in gettmarg() automatically restricts the range.
+ if rffi.getintfield(glob_buf, 'c_tm_wday') < -1:
+ raise Exception("day of week out of range")
+
+ rffi.setintfield(glob_buf, 'c_tm_year', y - 1900)
+ rffi.setintfield(glob_buf, 'c_tm_mon', rffi.getintfield(glob_buf,
'c_tm_mon') - 1)
+ rffi.setintfield(glob_buf, 'c_tm_wday', (rffi.getintfield(glob_buf,
'c_tm_wday') + 1) % 7)
+ rffi.setintfield(glob_buf, 'c_tm_yday', rffi.getintfield(glob_buf,
'c_tm_yday') - 1)
+
+ return glob_buf
+
+
+def gmtime(time_t):
+ seconds = time_t
+ t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw')
+ t_ref[0] = seconds
+ p = c_gmtime(t_ref)
+ lltype.free(t_ref, flavor='raw')
+ return _tm_to_tuple(p)
+
+
+def localtime(time_t):
+ seconds = time_t
+ t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw')
+ t_ref[0] = seconds
+ p = c_localtime(t_ref)
+ lltype.free(t_ref, flavor='raw')
+ return _tm_to_tuple(p)
+
+
+def mktime(tup):
+ buf = _gettmarg(tup)
+ rffi.setintfield(buf, "c_tm_wday", -1)
+ tt = c_mktime(buf)
+ if tt == -1 and rffi.getintfield(buf, "c_tm_wday") == -1:
+ raise Exception('mktime argument out of range')
+
+ return float(tt)
+
+
+def tzset():
+ c_tzset()
+
+
+def timegm(tup):
+ tz = os.environ.get('TZ')
+ os.environ['TZ'] = ''
+ tzset()
+
+ try:
+ tt = mktime(tup)
+ finally:
+ if tz:
+ os.environ['TZ'] = tz
+ else:
+ del os.environ['TZ']
+ tzset()
+
+ return tt
+
+
+def strftime(format, time_t):
+ """strftime(format[, tuple]) -> string
+
+ Convert a time tuple to a string according to a format specification.
+ See the library reference manual for formatting codes. When the time tuple
+ is not present, current time as returned by localtime() is used."""
+ buf_value = _gettmarg(time_t)
+
+ # Checks added to make sure strftime() does not crash Python by
+ # indexing blindly into some array for a textual representation
+ # by some bad index (fixes bug #897625).
+ # No check for year since handled in gettmarg().
+ if rffi.getintfield(buf_value, 'c_tm_mon') < 0 or
rffi.getintfield(buf_value, 'c_tm_mon') > 11:
+ raise Exception("month out of range")
+ if rffi.getintfield(buf_value, 'c_tm_mday') < 1 or
rffi.getintfield(buf_value, 'c_tm_mday') > 31:
+ raise Exception("day of month out of range")
+ if rffi.getintfield(buf_value, 'c_tm_hour') < 0 or
rffi.getintfield(buf_value, 'c_tm_hour') > 23:
+ raise Exception("hour out of range")
+ if rffi.getintfield(buf_value, 'c_tm_min') < 0 or
rffi.getintfield(buf_value, 'c_tm_min') > 59:
+ raise Exception("minute out of range")
+ if rffi.getintfield(buf_value, 'c_tm_sec') < 0 or
rffi.getintfield(buf_value, 'c_tm_sec') > 61:
+ raise Exception("seconds out of range")
+ if rffi.getintfield(buf_value, 'c_tm_yday') < 0 or
rffi.getintfield(buf_value, 'c_tm_yday') > 365:
+ raise Exception("day of year out of range")
+ if rffi.getintfield(buf_value, 'c_tm_isdst') < -1 or
rffi.getintfield(buf_value, 'c_tm_isdst') > 1:
+ raise Exception("daylight savings flag out of range")
+
+ if _WIN:
+ # check that the format string contains only valid directives
+ length = len(format)
+ i = 0
+ while i < length:
+ if format[i] == '%':
+ i += 1
+ if i < length and format[i] == '#':
+ # not documented by python
+ i += 1
+ if i >= length or format[i] not in "aAbBcdHIjmMpSUwWxXyYzZ%":
+ raise Exception("invalid format string")
+ i += 1
+
+ i = 1024
+ while True:
+ outbuf = lltype.malloc(rffi.CCHARP.TO, i, flavor='raw')
+ try:
+ buflen = c_strftime(outbuf, i, format, buf_value)
+ if buflen > 0 or i >= 256 * len(format):
+ # if the buffer is 256 times as long as the format,
+ # it's probably not failing for lack of room!
+ # More likely, the format yields an empty result,
+ # e.g. an empty format, or %Z when the timezone
+ # is unknown.
+ result = rffi.charp2strn(outbuf, intmask(buflen))
+ return result
+ finally:
+ lltype.free(outbuf, flavor='raw')
+ i += i
diff --git a/test/test_js_time.py b/test/test_js_time.py
new file mode 100644
--- /dev/null
+++ b/test/test_js_time.py
@@ -0,0 +1,97 @@
+from js.builtins.date import JsTime
+
+
+class TestJsTime(object):
+ # Sun, 17 Feb 2013 14:58:35 GMT
+ T = 1361113115765
+
+ def _new_t(self):
+ return JsTime(self.T)
+
+ def test_to_msecs(self):
+ t = self._new_t()
+ assert t.to_msec_epoc() == self.T
+
+ def test_year(self):
+ t = self._new_t()
+ assert t.year() == 2013
+
+ def test_month(self):
+ t = self._new_t()
+ assert t.month() == 2
+
+ def test_day(self):
+ t = self._new_t()
+ assert t.day() == 17
+
+ def test_hour(self):
+ t = self._new_t()
+ assert t.hour() == 14
+
+ def test_min(self):
+ t = self._new_t()
+ assert t.min() == 58
+
+ def test_sec(self):
+ t = self._new_t()
+ assert t.sec() == 35
+
+ def test_set_year(self):
+ t = self._new_t()
+ t.set_year(2012)
+ assert t.year() == 2012
+
+ def test_set_month(self):
+ t = self._new_t()
+ t.set_month(4)
+ assert t.month() == 4
+
+ def test_set_month_local(self):
+ t = self._new_t()
+ t.set_month(4, local=True)
+ assert t.month(local=True) == 4
+
+ def test_set_day(self):
+ t = self._new_t()
+ t.set_day(23)
+ assert t.day() == 23
+
+ def test_set_day_local(self):
+ t = self._new_t()
+ t.set_day(23, local=True)
+ assert t.day(local=True) == 23
+
+ def test_set_hour(self):
+ t = self._new_t()
+ t.set_hour(23)
+ assert t.hour() == 23
+
+ def test_set_hour_local(self):
+ t = self._new_t()
+ t.set_hour(23, local=True)
+ assert t.hour(local=True) == 23
+
+ def test_set_min(self):
+ t = self._new_t()
+ t.set_min(42)
+ assert t.min() == 42
+
+ def test_set_min_local(self):
+ t = self._new_t()
+ t.set_min(42, local=True)
+ assert t.min(local=True) == 42
+
+ def test_set_sec(self):
+ t = self._new_t()
+ t.set_sec(42)
+ assert t.sec() == 42
+
+ def test_set_sec_local(self):
+ t = self._new_t()
+ t.set_sec(42, local=True)
+ assert t.sec(local=True) == 42
+
+ def test_set_msec(self):
+ t = self._new_t()
+ t.set_msec(42)
+ assert t.msec() == 42
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit