[Scipy-svn] r2852 - in trunk/Lib/sandbox/timeseries: . src tests
scipy-svn@scip...
scipy-svn@scip...
Tue Mar 20 09:44:15 CDT 2007
Author: mattknox_ca
Date: 2007-03-20 09:44:08 -0500 (Tue, 20 Mar 2007)
New Revision: 2852
Modified:
trunk/Lib/sandbox/timeseries/__init__.py
trunk/Lib/sandbox/timeseries/setup.py
trunk/Lib/sandbox/timeseries/src/cseries.c
trunk/Lib/sandbox/timeseries/tcore.py
trunk/Lib/sandbox/timeseries/tdates.py
trunk/Lib/sandbox/timeseries/tests/test_dates.py
trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
trunk/Lib/sandbox/timeseries/tseries.py
Log:
major update. Ported Date class to C, removed a lot of stuff from tcore
Modified: trunk/Lib/sandbox/timeseries/__init__.py
===================================================================
--- trunk/Lib/sandbox/timeseries/__init__.py 2007-03-20 14:42:18 UTC (rev 2851)
+++ trunk/Lib/sandbox/timeseries/__init__.py 2007-03-20 14:44:08 UTC (rev 2852)
@@ -1,34 +1,42 @@
-"""TimeSeries
-
-Support for time series in numpy/scipy
-
-:author: Pierre GF Gerard-Marchant & Matt Knox
-:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
-:version: $Id$
-"""
+"""TimeSeries
+Support for time series in numpy/scipy
-__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
-__version__ = '1.0'
-__revision__ = "$Revision$"
-__date__ = '$Date$'
-
-import tcore
-from tcore import *
-import tdates
-from tdates import *
-import tseries
-from tseries import *
-import tmulti
-from tmulti import *
+:author: Pierre GF Gerard-Marchant & Matt Knox
+:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
+:version: $Id$
+"""
+
+
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
+__version__ = '1.0'
+__revision__ = "$Revision$"
+__date__ = '$Date$'
+
+# initialize python callbacks for C code
+import cseries as cs
+import parser
+from parser import DateFromString, DateTimeFromString
+cs.set_callback_DateFromString(DateFromString)
+cs.set_callback_DateTimeFromString(DateTimeFromString)
+
+import tcore
+from tcore import *
+import const
+import tdates
+from tdates import *
+import tseries
+from tseries import *
+import tmulti
+from tmulti import *
import reportlib
-from reportlib import *
-from addons import filters, interpolate
+from reportlib import *
+from addons import filters, interpolate
-
-__all__ = ['tdates', 'tseries','tmulti','reportlib','filters','interpolate']
-__all__ += tdates.__all__
-__all__ += tseries.__all__
+
+__all__ = ['const', 'tdates','parser','tseries','tmulti','reportlib','filters',
+ 'interpolate','DateFromString','DateTimeFromString']
+__all__ += tdates.__all__
+__all__ += tseries.__all__
__all__ += tmulti.__all__
__all__ += reportlib.__all__
-
Modified: trunk/Lib/sandbox/timeseries/setup.py
===================================================================
--- trunk/Lib/sandbox/timeseries/setup.py 2007-03-20 14:42:18 UTC (rev 2851)
+++ trunk/Lib/sandbox/timeseries/setup.py 2007-03-20 14:44:08 UTC (rev 2852)
@@ -25,5 +25,5 @@
if __name__ == "__main__":
from numpy.distutils.core import setup
#setup.update(nmasetup)
- config = configuration(top_path='').todict()
+ config = configuration(top_path='').todict()
setup(**config)
\ No newline at end of file
Modified: trunk/Lib/sandbox/timeseries/src/cseries.c
===================================================================
--- trunk/Lib/sandbox/timeseries/src/cseries.c 2007-03-20 14:42:18 UTC (rev 2851)
+++ trunk/Lib/sandbox/timeseries/src/cseries.c 2007-03-20 14:44:08 UTC (rev 2852)
@@ -1,8 +1,6 @@
#include <Python.h>
#include <datetime.h>
#include <structmember.h>
-#include <stdio.h>
-#include <string.h>
#include <time.h>
#include "arrayobject.h"
@@ -41,15 +39,16 @@
#define FR_SEC 9000 /* Secondly */
#define FR_UND -10000 /* Undefined */
-#define ADD_INT_TO_DICT(dict, key, val) \
- {PyObject *pyval = PyInt_FromLong(val); \
- PyDict_SetItemString(dict, key, pyval); \
- Py_DECREF(pyval); }
+#define INT_ERR_CODE -999
-#define DINFO_ERR -99
+#define HIGHFREQ_ORIG 719163
-#define CHECK_ASFREQ(result) if ((result) == DINFO_ERR) return NULL
+#define CHECK_ASFREQ(result) if ((result) == INT_ERR_CODE) return NULL
+static int get_freq_group(int freq) {
+ return (freq/1000)*1000;
+}
+
struct asfreq_info{
int from_week_end; //day the week ends on in the "from" frequency
int to_week_end; //day the week ends on in the "to" frequency
@@ -61,6 +60,129 @@
static struct asfreq_info NULL_AF_INFO;
+/*********************************************************
+** Python callbacks. These functions must be called by **
+** the module __init__ script **
+*********************************************************/
+static PyObject *
+set_callback(PyObject *args, PyObject **callback)
+{
+ PyObject *result = NULL;
+ PyObject *temp;
+
+ if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
+
+ if (!PyCallable_Check(temp)) {
+ PyErr_SetString(PyExc_TypeError, "parameter must be callable");
+ return NULL;
+ }
+
+ Py_XINCREF(temp); // Add a reference to new callback
+ Py_XDECREF(*callback); // Dispose of previous callback
+ *callback = temp; // Remember new callback
+ // Boilerplate to return "None"
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+ return result;
+}
+
+static PyObject *DateFromString = NULL;
+static char set_callback_DateFromString_doc[] =
+"set DateFromString function python callback";
+static PyObject *
+set_callback_DateFromString(PyObject *dummy, PyObject *args) {
+ return set_callback(args, &DateFromString);
+}
+
+static PyObject *DateTimeFromString = NULL;
+static char set_callback_DateTimeFromString_doc[] =
+"set DateTimeFromString function python callback";
+static PyObject *
+set_callback_DateTimeFromString(PyObject *dummy, PyObject *args) {
+ return set_callback(args, &DateTimeFromString);
+}
+
+/*********************************************************/
+
+static char *
+str_uppercase(char *str) {
+ if (str) {
+ int i, len=strlen(str);
+ char *result;
+ if((result = malloc((len + 1)*sizeof(char))) == NULL) {
+ return (char *)PyErr_NoMemory();
+ }
+ strcpy(result, str);
+
+ for (i=0;i<len;i++) {
+ switch(result[i])
+ {
+ case 'a': { result[i]='A'; break; }
+ case 'b': { result[i]='B'; break; }
+ case 'c': { result[i]='C'; break; }
+ case 'd': { result[i]='D'; break; }
+ case 'e': { result[i]='E'; break; }
+ case 'f': { result[i]='F'; break; }
+ case 'g': { result[i]='G'; break; }
+ case 'h': { result[i]='H'; break; }
+ case 'i': { result[i]='I'; break; }
+ case 'j': { result[i]='J'; break; }
+ case 'k': { result[i]='K'; break; }
+ case 'l': { result[i]='L'; break; }
+ case 'm': { result[i]='M'; break; }
+ case 'n': { result[i]='N'; break; }
+ case 'o': { result[i]='O'; break; }
+ case 'p': { result[i]='P'; break; }
+ case 'q': { result[i]='Q'; break; }
+ case 'r': { result[i]='R'; break; }
+ case 's': { result[i]='S'; break; }
+ case 't': { result[i]='T'; break; }
+ case 'u': { result[i]='U'; break; }
+ case 'v': { result[i]='V'; break; }
+ case 'w': { result[i]='W'; break; }
+ case 'x': { result[i]='X'; break; }
+ case 'y': { result[i]='Y'; break; }
+ case 'z': { result[i]='Z'; break; }
+ }
+ }
+
+ return result;
+ } else { return NULL; }
+}
+
+static char *
+str_replace(const char *s, const char *old, const char *new) {
+ char *ret;
+ int i, count = 0;
+ size_t newlen = strlen(new);
+ size_t oldlen = strlen(old);
+
+ for (i = 0; s[i] != '\0'; i++) {
+ if (strstr(&s[i], old) == &s[i]) {
+ count++;
+ i += oldlen - 1;
+ }
+ }
+
+ ret = malloc(i + 1 + count * (newlen - oldlen));
+ if (ret == NULL) {return (char *)PyErr_NoMemory();}
+
+ i = 0;
+ while (*s) {
+ if (strstr(s, old) == s) {
+ strcpy(&ret[i], new);
+ i += newlen;
+ s += oldlen;
+ } else {
+ ret[i++] = *s++;
+ }
+ }
+ ret[i] = '\0';
+
+ return ret;
+}
+
//DERIVED FROM mx.DateTime
/*
=====================================================
@@ -429,45 +551,36 @@
*/
-//////////////////////////////////////////////////////////
-static long minval_D_toHighFreq = 719163;
-///////////////////////////////////////////////////////////////////////
-static long absdatetime_hour(long absdate, long time) {
-
-}
-
///////////////////////////////////////////////////////////////////////
// helpers for frequency conversion routines //
static long DtoB_weekday(long fromDate) { return (((fromDate) / 7) * 5) + (fromDate)%7; }
-static long DtoB_WeekendToMonday(struct date_info dinfo) {
+static long DtoB_WeekendToMonday(long absdate, int day_of_week) {
- long absdate = dinfo.absdate;
- if (dinfo.day_of_week > 4) {
+ if (day_of_week > 4) {
//change to Monday after weekend
- absdate += (7 - dinfo.day_of_week);
+ absdate += (7 - day_of_week);
}
return DtoB_weekday(absdate);
}
-static long DtoB_WeekendToFriday(struct date_info dinfo) {
+static long DtoB_WeekendToFriday(long absdate, int day_of_week) {
- long absdate = dinfo.absdate;
- if (dinfo.day_of_week > 4) {
+ if (day_of_week > 4) {
//change to friday before weekend
- absdate -= (dinfo.day_of_week - 4);
+ absdate -= (day_of_week - 4);
}
return DtoB_weekday(absdate);
}
static long absdate_from_ymd(int y, int m, int d) {
struct date_info tempDate;
- if (dInfoCalc_SetFromDateAndTime(&tempDate, y, m, d, 0, 0, 0, GREGORIAN_CALENDAR)) return DINFO_ERR;
+ if (dInfoCalc_SetFromDateAndTime(&tempDate, y, m, d, 0, 0, 0, GREGORIAN_CALENDAR)) return INT_ERR_CODE;
return tempDate.absdate;
}
@@ -483,7 +596,7 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, fromDate,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
if (dinfo.month > af_info->to_a_year_end) { return (long)(dinfo.year + 1); }
else { return (long)(dinfo.year); }
}
@@ -493,7 +606,7 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, fromDate,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
return (long)((dinfo.year - 1) * 4 + dinfo.quarter);
}
@@ -501,7 +614,7 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, fromDate,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
return (long)((dinfo.year - 1) * 12 + dinfo.month);
}
@@ -513,12 +626,12 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, fromDate,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
if (relation == 'B') {
- return DtoB_WeekendToFriday(dinfo);
+ return DtoB_WeekendToFriday(dinfo.absdate, dinfo.day_of_week);
} else {
- return DtoB_WeekendToMonday(dinfo);
+ return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week);
}
}
@@ -526,7 +639,7 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, fromDate,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
if (dinfo.day_of_week > 4) {
return -1;
@@ -539,9 +652,9 @@
static long asfreq_DtoD(long fromDate, char relation, struct asfreq_info *af_info) { return fromDate; }
static long asfreq_DtoHIGHFREQ(long fromDate, char relation, long periodsPerDay) {
- if (fromDate >= minval_D_toHighFreq) {
- if (relation == 'B') { return (fromDate - minval_D_toHighFreq)*(periodsPerDay) + 1; }
- else { return (fromDate - minval_D_toHighFreq + 1)*(periodsPerDay); }
+ if (fromDate >= HIGHFREQ_ORIG) {
+ if (relation == 'B') { return (fromDate - HIGHFREQ_ORIG)*(periodsPerDay) + 1; }
+ else { return (fromDate - HIGHFREQ_ORIG + 1)*(periodsPerDay); }
} else { return -1; }
}
@@ -555,7 +668,7 @@
//************ FROM SECONDLY ***************
static long asfreq_StoD(long fromDate, char relation, struct asfreq_info *af_info)
- { return (fromDate - 1)/(60*60*24) + minval_D_toHighFreq; }
+ { return (fromDate - 1)/(60*60*24) + HIGHFREQ_ORIG; }
static long asfreq_StoA(long fromDate, char relation, struct asfreq_info *af_info)
{ return asfreq_DtoA(asfreq_StoD(fromDate, relation, &NULL_AF_INFO), relation, af_info); }
@@ -577,7 +690,7 @@
//************ FROM MINUTELY ***************
static long asfreq_TtoD(long fromDate, char relation, struct asfreq_info *af_info)
- { return (fromDate - 1)/(60*24) + minval_D_toHighFreq; }
+ { return (fromDate - 1)/(60*24) + HIGHFREQ_ORIG; }
static long asfreq_TtoA(long fromDate, char relation, struct asfreq_info *af_info)
{ return asfreq_DtoA(asfreq_TtoD(fromDate, relation, &NULL_AF_INFO), relation, af_info); }
@@ -602,7 +715,7 @@
//************ FROM HOURLY ***************
static long asfreq_HtoD(long fromDate, char relation, struct asfreq_info *af_info)
- { return (fromDate - 1)/24 + minval_D_toHighFreq; }
+ { return (fromDate - 1)/24 + HIGHFREQ_ORIG; }
static long asfreq_HtoA(long fromDate, char relation, struct asfreq_info *af_info)
{ return asfreq_DtoA(asfreq_HtoD(fromDate, relation, &NULL_AF_INFO), relation, af_info); }
static long asfreq_HtoQ(long fromDate, char relation, struct asfreq_info *af_info)
@@ -671,10 +784,10 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, asfreq_WtoD(fromDate, relation, af_info),
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
- if (relation == 'B') { return DtoB_WeekendToMonday(dinfo); }
- else { return DtoB_WeekendToFriday(dinfo); }
+ if (relation == 'B') { return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week); }
+ else { return DtoB_WeekendToFriday(dinfo.absdate, dinfo.day_of_week); }
}
static long asfreq_WtoH(long fromDate, char relation, struct asfreq_info *af_info)
@@ -697,11 +810,11 @@
if (relation == 'B') {
MtoD_ym(fromDate, &y, &m);
- if ((absdate = absdate_from_ymd(y, m, 1)) == DINFO_ERR) return DINFO_ERR;
+ if ((absdate = absdate_from_ymd(y, m, 1)) == INT_ERR_CODE) return INT_ERR_CODE;
return absdate;
} else {
MtoD_ym(fromDate+1, &y, &m);
- if ((absdate = absdate_from_ymd(y, m, 1)) == DINFO_ERR) return DINFO_ERR;
+ if ((absdate = absdate_from_ymd(y, m, 1)) == INT_ERR_CODE) return INT_ERR_CODE;
return absdate-1;
}
}
@@ -723,10 +836,10 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, asfreq_MtoD(fromDate, relation, &NULL_AF_INFO),
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
- if (relation == 'B') { return DtoB_WeekendToMonday(dinfo); }
- else { return DtoB_WeekendToFriday(dinfo); }
+ if (relation == 'B') { return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week); }
+ else { return DtoB_WeekendToFriday(dinfo.absdate, dinfo.day_of_week); }
}
static long asfreq_MtoH(long fromDate, char relation, struct asfreq_info *af_info)
@@ -749,11 +862,11 @@
if (relation == 'B') {
QtoD_ym(fromDate, &y, &m);
- if ((absdate = absdate_from_ymd(y, m, 1)) == DINFO_ERR) return DINFO_ERR;
+ if ((absdate = absdate_from_ymd(y, m, 1)) == INT_ERR_CODE) return INT_ERR_CODE;
return absdate;
} else {
QtoD_ym(fromDate+1, &y, &m);
- if ((absdate = absdate_from_ymd(y, m, 1)) == DINFO_ERR) return DINFO_ERR;
+ if ((absdate = absdate_from_ymd(y, m, 1)) == INT_ERR_CODE) return INT_ERR_CODE;
return absdate - 1;
}
}
@@ -777,10 +890,10 @@
struct date_info dinfo;
if (dInfoCalc_SetFromAbsDate(&dinfo, asfreq_QtoD(fromDate, relation, &NULL_AF_INFO),
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
- if (relation == 'B') { return DtoB_WeekendToMonday(dinfo); }
- else { return DtoB_WeekendToFriday(dinfo); }
+ if (relation == 'B') { return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week); }
+ else { return DtoB_WeekendToFriday(dinfo.absdate, dinfo.day_of_week); }
}
@@ -808,7 +921,7 @@
final_adj = -1;
}
absdate = absdate_from_ymd(year, month, 1);
- if (absdate == DINFO_ERR) return DINFO_ERR;
+ if (absdate == INT_ERR_CODE) return INT_ERR_CODE;
return absdate + final_adj;
}
@@ -836,7 +949,7 @@
static long asfreq_AtoB(long fromDate, char relation, struct asfreq_info *af_info) {
- long absdate, year;
+ long year;
int month = (af_info->from_a_year_end + 1) % 12;
struct date_info dailyDate;
@@ -848,8 +961,8 @@
if (dInfoCalc_SetFromDateAndTime(&dailyDate,
year,month,1, 0, 0, 0,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
- return DtoB_WeekendToMonday(dailyDate);
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
+ return DtoB_WeekendToMonday(dailyDate.absdate, dailyDate.day_of_week);
} else {
long absdate;
@@ -858,15 +971,15 @@
if (dInfoCalc_SetFromDateAndTime(&dailyDate,
year,month,1, 0, 0, 0,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
absdate = dailyDate.absdate - 1;
if(dInfoCalc_SetFromAbsDate(&dailyDate,
absdate,
- GREGORIAN_CALENDAR)) return DINFO_ERR;
+ GREGORIAN_CALENDAR)) return INT_ERR_CODE;
- return DtoB_WeekendToFriday(dailyDate);
+ return DtoB_WeekendToFriday(dailyDate.absdate, dailyDate.day_of_week);
}
}
@@ -884,9 +997,11 @@
// return a pointer to appropriate conversion function
static long (*get_asfreq_func(int fromFreq, int toFreq, int forConvert))(long, char, struct asfreq_info*) {
- int fromGroup = (fromFreq/1000)*1000;
- int toGroup = (toFreq/1000)*1000;
+ int fromGroup = get_freq_group(fromFreq);
+ int toGroup = get_freq_group(toFreq);
+ if (fromGroup == FR_UND) { fromGroup = FR_DAY; }
+
switch(fromGroup)
{
case FR_ANN:
@@ -1038,9 +1153,11 @@
int maxBusDaysPerYear, maxBusDaysPerQuarter, maxBusDaysPerMonth;
int maxDaysPerYear, maxDaysPerQuarter, maxDaysPerMonth;
- int fromGroup = (fromFreq/1000)*1000;
- int toGroup = (toFreq/1000)*1000;
+ int fromGroup = get_freq_group(fromFreq);
+ int toGroup = get_freq_group(toFreq);
+ if (fromGroup == FR_UND) { fromGroup = FR_DAY; }
+
maxBusDaysPerYear = 262;
maxBusDaysPerQuarter = 66;
maxBusDaysPerMonth = 23;
@@ -1145,8 +1262,8 @@
static void get_asfreq_info(int fromFreq, int toFreq, struct asfreq_info *af_info) {
- int fromGroup = (fromFreq/1000)*1000;
- int toGroup = (toFreq/1000)*1000;
+ int fromGroup = get_freq_group(fromFreq);
+ int toGroup = get_freq_group(toFreq);
switch(fromGroup)
{
@@ -1170,10 +1287,1250 @@
}
-static char cseries_convert_doc[] = "";
+static int dInfo_year(struct date_info *dateObj) { return dateObj->year; }
+static int dInfo_quarter(struct date_info *dateObj) { return dateObj->quarter; }
+static int dInfo_month(struct date_info *dateObj) { return dateObj->month; }
+static int dInfo_day(struct date_info *dateObj) { return dateObj->day; }
+static int dInfo_day_of_year(struct date_info *dateObj) { return dateObj->day_of_year; }
+static int dInfo_day_of_week(struct date_info *dateObj) { return dateObj->day_of_week; }
+static int dInfo_week(struct date_info *dateObj) { return dInfoCalc_ISOWeek(dateObj); }
+static int dInfo_hour(struct date_info *dateObj) { return dateObj->hour; }
+static int dInfo_minute(struct date_info *dateObj) { return dateObj->minute; }
+static int dInfo_second(struct date_info *dateObj) { return (int)dateObj->second; }
+
+static double getAbsTime(int freq, long dailyDate, long originalDate) {
+
+ long startOfDay, periodsPerDay;
+
+ switch(freq)
+ {
+ case FR_HR:
+ periodsPerDay = 24;
+ break;
+ case FR_MIN:
+ periodsPerDay = 24*60;
+ break;
+ case FR_SEC:
+ periodsPerDay = 24*60*60;
+ break;
+ default:
+ return 0;
+ }
+
+ startOfDay = asfreq_DtoHIGHFREQ(dailyDate, 'B', periodsPerDay);
+ return (24*60*60)*((double)(originalDate - startOfDay))/((double)periodsPerDay);
+}
+
+/************************************************************
+** Date type definition
+************************************************************/
+
+typedef struct {
+ PyObject_HEAD
+ int freq; /* frequency of date */
+ int value; /* integer representation of date */
+ PyObject* cached_vals;
+} DateObject;
+
+/* Forward declarations */
+static PyTypeObject DateType;
+#define DateObject_Check(op) PyObject_TypeCheck(op, &DateType)
+
+static void
+DateObject_dealloc(DateObject* self) {
+ Py_XDECREF(self->cached_vals);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static PyObject *freq_dict, *freq_dict_rev, *freq_constants;
+
+#define DICT_SETINT_STRKEY(dict, key, val) \
+ {PyObject *pyval = PyInt_FromLong(val); \
+ PyDict_SetItemString(dict, key, pyval); \
+ Py_DECREF(pyval); }
+
+#define ADD_FREQ_CONSTANT(const_name, val) \
+ DICT_SETINT_STRKEY(freq_constants, const_name, val)
+
+#define INIT_FREQ(const_name, key, aliases) \
+ {PyObject *pykey = PyInt_FromLong(key); \
+ PyDict_SetItem(freq_dict, pykey, aliases); \
+ PyDict_SetItemString(freq_constants, const_name, pykey); \
+ Py_DECREF(pykey); \
+ Py_DECREF(aliases); }
+
+
+static int init_freq_group(int num_items, int num_roots, int group_const,
+ char item_abbrevs[][2][10], char group_prefixes[][10],
+ char item_const_names[][10]) {
+
+ int i;
+
+ for (i = 0; i < num_items; i++) {
+
+ PyObject *aliases;
+ int j, size, k;
+
+ if (i == 0) { k = 3; } else { k = 2; }
+
+ size = num_roots * k;
+
+ aliases = PyTuple_New(size);
+
+ for (j = 0; j < num_roots; j++) {
+ PyObject *alias_v1, *alias_v2;
+ char *root, *alt;
+
+ if ((root = malloc((26) * sizeof(char))) == NULL) return INT_ERR_CODE;
+ if ((alt = malloc((26) * sizeof(char))) == NULL) return INT_ERR_CODE;
+
+ strcpy(root, group_prefixes[j]);
+ strcpy(alt, group_prefixes[j]);
+
+ if (i == 0) {
+ PyObject *alias = PyString_FromString(root);
+ PyTuple_SET_ITEM(aliases, j*k + 2, alias);
+ }
+
+ strcat(root, "-");
+ strcat(root, item_abbrevs[i][0]);
+ strcat(alt, "-");
+ strcat(alt, item_abbrevs[i][1]);
+
+ alias_v1 = PyString_FromString(root);
+ alias_v2 = PyString_FromString(alt);
+
+ free(root);
+ free(alt);
+
+ PyTuple_SET_ITEM(aliases, j*k, alias_v1);
+ PyTuple_SET_ITEM(aliases, j*k + 1, alias_v2);
+ }
+
+ INIT_FREQ(item_const_names[i], group_const+i, aliases);
+ }
+
+ return 0;
+}
+
+/* take a dictionary with integer keys and tuples of strings for values,
+ and populate a dictionary with all the strings as keys and integers
+ for values */
+static int reverse_dict(PyObject *source, PyObject *dest) {
+
+ PyObject *key, *value;
+
+ int pos = 0;
+
+ while (PyDict_Next(source, &pos, &key, &value)) {
+ PyObject *tuple_iter;
+ PyObject *item;
+
+ if((tuple_iter = PyObject_GetIter(value)) == NULL) return INT_ERR_CODE;
+
+ while (item = PyIter_Next(tuple_iter)) {
+ PyDict_SetItem(dest, item, key);
+ Py_DECREF(item);
+ }
+ Py_DECREF(tuple_iter);
+ }
+ return 0;
+}
+
+static int build_freq_dict() {
+
+ char ANN_prefixes[8][10] = { "A", "Y", "ANN", "ANNUAL", "ANNUALLY",
+ "YR", "YEAR", "YEARLY" };
+ char WK_prefixes[4][10] = { "W", "WK", "WEEK", "WEEKLY" };
+
+ /* Note: order of this array must match up with how the Annual
+ frequency constants are lined up */
+ char month_names[12][2][10] = {
+ { "DEC", "DECEMBER" },
+ { "JAN", "JANUARY" },
+ { "FEB", "FEBRUARY" },
+ { "MAR", "MARCH" },
+ { "APR", "APRIL" },
+ { "MAY", "MAY" },
+ { "JUN", "JUNE" },
+ { "JUL", "JULY" },
+ { "AUG", "AUGUST" },
+ { "SEP", "SEPTEMBER" },
+ { "OCT", "OCTOBER" },
+ { "NOV", "NOVEMBER" }};
+
+ char ANN_const_names[12][10] = {
+ "FR_ANNDEC",
+ "FR_ANNJAN",
+ "FR_ANNFEB",
+ "FR_ANNMAR",
+ "FR_ANNAPR",
+ "FR_ANNMAY",
+ "FR_ANNJUN",
+ "FR_ANNJUL",
+ "FR_ANNAUG",
+ "FR_ANNSEP",
+ "FR_ANNOCT",
+ "FR_ANNNOV"};
+
+ char day_names[7][2][10] = {
+ { "SUN", "SUNDAY" },
+ { "MON", "MONDAY" },
+ { "TUE", "TUESDAY" },
+ { "WED", "WEDNESDAY" },
+ { "THU", "THURSDAY" },
+ { "FRI", "FRIDAY" },
+ { "SAT", "SATURDAY" }};
+
+ char WK_const_names[7][10] = {
+ "FR_WKSUN",
+ "FR_WKMON",
+ "FR_WKTUE",
+ "FR_WKWED",
+ "FR_WKTHU",
+ "FR_WKFRI",
+ "FR_WKSAT"};
+
+ PyObject *aliases;
+
+ freq_dict = PyDict_New();
+ freq_dict_rev = PyDict_New();
+ freq_constants = PyDict_New();
+
+ aliases = Py_BuildValue("(ssss)", "Q", "QTR", "QUARTER", "QUARTERLY");
+ INIT_FREQ("FR_QTR", FR_QTR, aliases);
+
+ aliases = Py_BuildValue("(ssss)", "M", "MTH", "MONTH", "MONTHLY");
+ INIT_FREQ("FR_MTH", FR_MTH, aliases);
+
+ aliases = Py_BuildValue("(ssss)", "B", "BUS", "BUSINESS", "BUSINESSLY");
+ INIT_FREQ("FR_BUS", FR_BUS, aliases);
+
+ aliases = Py_BuildValue("(ssss)", "D", "DAY", "DLY", "DAILY");
+ INIT_FREQ("FR_DAY", FR_DAY, aliases);
+
+ aliases = Py_BuildValue("(sssss)", "H", "HR", "HOUR", "HRLY", "HOURLY");
+ INIT_FREQ("FR_HR", FR_HR, aliases);
+
+ aliases = Py_BuildValue("(ssss)", "T", "MIN", "MINUTE", "MINUTELY");
+ INIT_FREQ("FR_MIN", FR_MIN, aliases);
+
+ aliases = Py_BuildValue("(ssss)", "S", "SEC", "SECOND", "SECONDLY");
+ INIT_FREQ("FR_SEC", FR_SEC, aliases);
+
+ aliases = Py_BuildValue("(ssss)", "U", "UND", "UNDEF", "UNDEFINED");
+ INIT_FREQ("FR_UND", FR_UND, aliases);
+
+ ADD_FREQ_CONSTANT("FR_ANN", FR_ANN);
+
+ if(init_freq_group(12, 8, FR_ANN,
+ month_names, ANN_prefixes, ANN_const_names) == INT_ERR_CODE) {
+ return INT_ERR_CODE;
+ }
+
+ ADD_FREQ_CONSTANT("FR_WK", FR_WK);
+
+ if(init_freq_group(7, 4, FR_WK,
+ day_names, WK_prefixes, WK_const_names) == INT_ERR_CODE) {
+ return INT_ERR_CODE;
+ }
+
+ if(reverse_dict(freq_dict, freq_dict_rev) == INT_ERR_CODE) {
+ return INT_ERR_CODE;
+ }
+
+ return 0;
+}
+
+
+/* take user specified frequency and convert to int representation
+ of the frequency */
+static int check_freq(PyObject *freq_spec) {
+
+ if (PyInt_Check(freq_spec)) {
+ return (int)PyInt_AsLong(freq_spec);
+ } else if (PyString_Check(freq_spec)) {
+ char *freq_str, *freq_str_uc;
+ PyObject *freq_val;
+
+ freq_str = PyString_AsString(freq_spec);
+ if((freq_str_uc = str_uppercase(freq_str)) == NULL) {return INT_ERR_CODE;}
+
+ freq_val = PyDict_GetItemString(freq_dict_rev, freq_str_uc);
+
+ free(freq_str_uc);
+
+ if (freq_val == NULL) {
+ PyErr_SetString(PyExc_ValueError, "invalid frequency specification");
+ return INT_ERR_CODE;
+ } else {
+ int ret_val = (int)PyInt_AsLong(freq_val);
+ return ret_val;
+ }
+ } else if (freq_spec == Py_None) {
+ return FR_UND;
+ } else {
+ int retval = (int)PyInt_AsLong(freq_spec);
+ if (PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError, "invalid frequency specification");
+ return INT_ERR_CODE;
+ } else { return retval; }
+ }
+
+}
+
static PyObject *
-cseries_convert(PyObject *self, PyObject *args)
+DateObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+
+ DateObject *self;
+
+ self = (DateObject*)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ // initialize attributes that need initializing in here
+ self->freq = FR_UND;
+ self->value = -1;
+ }
+
+ return (PyObject *)self;
+}
+
+/* for use in C code */
+static DateObject *
+DateObject_New() {
+ PyObject *dummy;
+ return (DateObject*)DateObject_new(&DateType, dummy, dummy);
+}
+
+#define INIT_ERR(errortype, errmsg) PyErr_SetString(errortype,errmsg);return -1
+
+static int
+DateObject_init(DateObject *self, PyObject *args, PyObject *kwds) {
+
+ PyObject *freq=NULL, *value=NULL, *datetime=NULL, *string=NULL;
+ char *INSUFFICIENT_MSG = "insufficient parameters to initialize Date";
+
+ int def_info=INT_ERR_CODE;
+
+ int year=def_info, month=def_info, day=def_info, quarter=def_info,
+ hour=def_info, minute=def_info, second=def_info;
+
+ int free_dt=0;
+
+ static char *kwlist[] = {"freq", "value", "string",
+ "year", "month", "day", "quarter",
+ "hour", "minute", "second",
+ "datetime", NULL};
+
+ if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiiiiiiiO", kwlist,
+ &freq, &value, &string,
+ &year, &month, &day, &quarter,
+ &hour, &minute, &second,
+ &datetime)) return -1;
+
+ if (PyObject_HasAttrString(freq, "freq")) {
+ PyObject *freq_attr = PyObject_GetAttrString(freq, "freq");
+ self->freq = PyInt_AS_LONG(freq_attr);
+ Py_DECREF(freq_attr);
+ } else {
+ if((self->freq = check_freq(freq)) == INT_ERR_CODE) return -1;
+ }
+
+ if ((value && PyString_Check(value)) || string) {
+
+ PyObject *string_arg = PyTuple_New(1);
+ int freq_group = get_freq_group(self->freq);
+
+ free_dt = 1;
+
+ if (!string) {
+ string = value;
+ }
+
+ PyTuple_SET_ITEM(string_arg, 0, string);
+ Py_INCREF(string);
+
+ if (freq_group == FR_HR ||
+ freq_group == FR_MIN ||
+ freq_group == FR_SEC)
+ { datetime = PyEval_CallObject(DateTimeFromString, string_arg); }
+ else { datetime = PyEval_CallObject(DateFromString, string_arg); }
+
+ Py_DECREF(string_arg);
+
+ value = NULL;
+ }
+
+ if (value) {
+ self->value = PyInt_AsLong(value);
+ } else {
+
+ int freq_group = get_freq_group(self->freq);
+
+ if (datetime) {
+ year=PyDateTime_GET_YEAR(datetime);
+ month=PyDateTime_GET_MONTH(datetime);
+ day=PyDateTime_GET_DAY(datetime);
+ hour=PyDateTime_DATE_GET_HOUR(datetime);
+ minute=PyDateTime_DATE_GET_MINUTE(datetime);
+ second=PyDateTime_DATE_GET_SECOND(datetime);
+ }
+
+ if (!datetime) {
+
+ // First, some basic checks.....
+ if (year == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ }
+ if (self->freq == FR_BUS ||
+ self->freq == FR_DAY ||
+ self->freq == FR_WK ||
+ self->freq == FR_UND) {
+ if (month == def_info || day == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ }
+
+ // if FR_BUS, check for week day
+
+ } else if (self->freq == FR_MTH) {
+ if (month == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ }
+ } else if (self->freq == FR_QTR) {
+ if (quarter == def_info && month == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ } else if (month != def_info) {
+ quarter = (int)asfreq_MtoQ(month, '-', &NULL_AF_INFO);
+ }
+ } else if (self->freq == FR_SEC) {
+ if (month == def_info ||
+ day == def_info ||
+ second == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ }
+ if (hour == def_info) {
+ hour = second/3600;
+ minute = (second % 3600)/60;
+ second = second % 60;
+ } else if (minute == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ }
+ } else if (self->freq == FR_MIN) {
+ if (month == def_info ||
+ day == def_info ||
+ minute == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ }
+ if (hour == def_info) {
+ hour = minute/60;
+ minute = minute % 60;
+ }
+ } else if (self->freq == FR_HR) {
+ if (month == def_info ||
+ day == def_info ||
+ hour == def_info) {
+ INIT_ERR(PyExc_ValueError, INSUFFICIENT_MSG);
+ }
+ }
+
+ }
+
+ if (self->freq == FR_SEC) {
+ long absdays, delta;
+ absdays = absdate_from_ymd(year, month, day);
+ delta = (absdays - HIGHFREQ_ORIG);
+ self->value = (int)(delta*86400 + hour*3600 + minute*60 + second + 1);
+ } else if (self->freq == FR_MIN) {
+ long absdays, delta;
+ absdays = absdate_from_ymd(year, month, day);
+ delta = (absdays - HIGHFREQ_ORIG);
+ self->value = (int)(delta*1440 + hour*60 + minute + 1);
+ } else if (self->freq == FR_HR) {
+ long absdays, delta;
+ absdays = absdate_from_ymd(year, month, day);
+ delta = (absdays - HIGHFREQ_ORIG);
+ self->value = (int)(delta*24 + hour + 1);
+ } else if (self->freq == FR_DAY) {
+ self->value = (int)absdate_from_ymd(year, month, day);
+ } else if (self->freq == FR_UND) {
+ self->value = (int)absdate_from_ymd(year, month, day);
+ } else if (self->freq == FR_BUS) {
+ long weeks, days;
+ days = absdate_from_ymd(year, month, day);
+ weeks = days/7;
+ self->value = (int)(days - weeks*2);
+ } else if (freq_group == FR_WK) {
+ int adj_ordinal;
+ int ordinal = (int)absdate_from_ymd(year, month, day);
+ int day_adj = (7 - (self->freq - FR_WK)) % 7;
+
+ adj_ordinal = ordinal + ((7 - day_adj) - ordinal % 7) % 7;
+ self->value = adj_ordinal/7;
+ } else if (self->freq == FR_MTH) {
+ self->value = (year-1)*12 + month;
+ } else if (self->freq == FR_QTR) {
+ self->value = (year-1)*4 + quarter;
+ } else if (freq_group == FR_ANN) {
+ self->value = year;
+ }
+
+ }
+
+ if (free_dt) { Py_DECREF(datetime); }
+
+ return 0;
+}
+
+static PyMemberDef DateObject_members[] = {
+ {"freq", T_INT, offsetof(DateObject, freq), 0,
+ "frequency"},
+ {"value", T_INT, offsetof(DateObject, value), 0,
+ "integer representation of the Date"},
+ {NULL} /* Sentinel */
+};
+
+static char DateObject_toordinal_doc[] =
+"Return the proleptic Gregorian ordinal of the date, where January 1 of\n"
+"year 1 has ordinal 1";
+static PyObject *
+DateObject_toordinal(DateObject* self)
{
+ if (self->freq == FR_DAY) {
+ return PyInt_FromLong(self->value);
+ } else {
+ long (*toDaily)(long, char, struct asfreq_info*) = NULL;
+ struct asfreq_info af_info;
+
+ toDaily = get_asfreq_func(self->freq, FR_DAY, 0);
+ get_asfreq_info(self->freq, FR_DAY, &af_info);
+
+ return PyInt_FromLong(toDaily(self->value, 'A', &af_info));
+ }
+}
+
+static char DateObject_asfreq_doc[] =
+"Returns a date converted to a specified frequency.\n\n"
+":Parameters:\n"
+" - freq : string/int\n"
+" Frequency to convert the Date to. Accepts any valid frequency\n"
+" specification (string or integer)\n"
+" - relation :string *['After']*\n"
+" Applies only when converting a lower frequency Date to a higher\n"
+" frequency Date, or when converting a weekend Date to a business\n"
+" frequency Date. Valid values are 'before', 'after', 'b', and 'a'.";
+static PyObject *
+DateObject_asfreq(DateObject *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *freq=NULL;
+ char *relation_raw=NULL;
+ char *relation_uc;
+ char relation;
+ int invalid_relation=0;
+ int toFreq;
+ int result_val;
+ DateObject *result = DateObject_New();
+
+ static char *kwlist[] = {"freq", "relation", NULL};
+
+ long (*asfreq_func)(long, char, struct asfreq_info*) = NULL;
+ struct asfreq_info af_info;
+
+ if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|s", kwlist,
+ &freq, &relation_raw)) return NULL;
+
+ if(relation_raw) {
+ if (strlen(relation_raw) > 0) {
+ if((relation_uc = str_uppercase(relation_raw)) == NULL)
+ {return PyErr_NoMemory();}
+
+ if (strcmp(relation_uc, "BEFORE") == 0 ||
+ strcmp(relation_uc, "B") == 0 ||
+ strcmp(relation_uc, "AFTER") == 0 ||
+ strcmp(relation_uc, "A") == 0) {
+ relation = relation_uc[0];
+ } else { invalid_relation=1; }
+ } else {
+ invalid_relation=1;
+ }
+
+ if (invalid_relation) {
+ PyErr_SetString(PyExc_ValueError,"Invalid relation specification");
+ return NULL;
+ }
+ } else {
+ relation = 'A';
+ }
+
+ if ((toFreq = check_freq(freq)) == INT_ERR_CODE) return NULL;
+
+ get_asfreq_info(self->freq, toFreq, &af_info);
+ asfreq_func = get_asfreq_func(self->freq, toFreq, 0);
+
+ result_val = asfreq_func(self->value, relation, &af_info);
+
+ result->freq = toFreq;
+ result->value = result_val;
+
+ return (PyObject*)result;
+
+}
+
+static char DateObject_strfmt_doc[] =
+"Returns string representation of Date object according to format specified.\n\n"
+":Parameters:\n"
+" - fmt : string\n"
+" Formatting string. Uses the same directives as in the time.strftime\n"
+" function in the standard Python time module. In addition, a %q directive\n"
+" directive is recognized which represents the 'quarter' of the date";
+static PyObject *
+DateObject_strfmt(DateObject *self, PyObject *args)
+{
+
+ char *orig_fmt_str, *fmt_str;
+ char *result;
+
+ char extra_fmts[1][2][10] = {{"%q", "^`XZ`^"}};
+ int extra_fmts_found[1] = {0};
+ int extra_fmts_found_one = 0;
+ struct tm c_date;
+ struct date_info tempDate;
+ long absdate;
+ double abstime;
+ int i, result_len, special_found=0;
+ PyObject *py_result;
+
+ long (*toDaily)(long, char, struct asfreq_info*) = NULL;
+ struct asfreq_info af_info;
+
+ if (!PyArg_ParseTuple(args, "s:strfmt(fmt)", &orig_fmt_str)) return NULL;
+
+ toDaily = get_asfreq_func(self->freq, FR_DAY, 0);
+ get_asfreq_info(self->freq, FR_DAY, &af_info);
+
+ absdate = toDaily(self->value, 'A', &af_info);
+ abstime = getAbsTime(self->freq, absdate, self->value);
+
+ if(dInfoCalc_SetFromAbsDateTime(&tempDate, absdate, abstime,
+ GREGORIAN_CALENDAR)) return NULL;
+
+ // populate standard C date struct with info from our date_info struct
+ c_date.tm_sec = (int)tempDate.second;
+ c_date.tm_min = tempDate.minute;
+ c_date.tm_hour = tempDate.hour;
+ c_date.tm_mday = tempDate.day;
+ c_date.tm_mon = tempDate.month - 1;
+ c_date.tm_year = tempDate.year - 1900;
+ c_date.tm_wday = tempDate.day_of_week;
+ c_date.tm_yday = tempDate.day_of_year;
+ c_date.tm_isdst = -1;
+
+ result_len = strlen(orig_fmt_str) + 50;
+ if ((result = malloc(result_len * sizeof(char))) == NULL) {return PyErr_NoMemory();}
+
+ fmt_str = orig_fmt_str;
+
+ // replace any special format characters with their place holder
+ for(i=0; i < 1; i++) {
+ char *special_loc;
+ if ((special_loc = strstr(fmt_str,extra_fmts[i][0])) != NULL) {
+ char *tmp_str = fmt_str;
+ fmt_str = str_replace(fmt_str, extra_fmts[i][0],
+ extra_fmts[i][1]);
+ /* only free the previous loop value if this is not the first
+ special format string found */
+ if (extra_fmts_found_one) { free(tmp_str); }
+
+ if (fmt_str == NULL) {return NULL;}
+
+ extra_fmts_found[i] = 1;
+ extra_fmts_found_one = 1;
+ }
+ }
+
+ strftime(result, result_len, fmt_str, &c_date);
+ if (extra_fmts_found_one) { free(fmt_str); }
+
+ // replace any place holders with the appropriate value
+ for(i=0; i < 1; i++) {
+ if (extra_fmts_found[i]) {
+ char *tmp_str = result;
+ char *extra_str;
+
+ if(strcmp(extra_fmts[i][0], "%q") == 0) {
+ if ((extra_str = malloc(2 * sizeof(char))) == NULL) {
+ free(tmp_str);
+ return PyErr_NoMemory();
+ }
+
+ sprintf(extra_str, "%i", tempDate.quarter);
+ } else {
+ PyErr_SetString(PyExc_RuntimeError,"Unrecogized fmt string");
+ return NULL;
+ }
+
+ result = str_replace(result, extra_fmts[i][1], extra_str);
+ free(tmp_str);
+ if (result == NULL) { return NULL; }
+ }
+ }
+
+ py_result = PyString_FromString(result);
+ free(result);
+
+ return py_result;
+}
+
+static PyObject *
+DateObject___str__(DateObject* self)
+{
+
+ int freq_group = get_freq_group(self->freq);
+ PyObject *string_arg, *retval;
+
+ if (freq_group == FR_ANN) { string_arg = Py_BuildValue("(s)", "%Y"); }
+ else if (freq_group == FR_QTR) { string_arg = Py_BuildValue("(s)", "%YQ%q"); }
+ else if (freq_group == FR_MTH) { string_arg = Py_BuildValue("(s)", "%b-%Y"); }
+ else if (freq_group == FR_DAY ||
+ freq_group == FR_BUS ||
+ freq_group == FR_WK ||
+ freq_group == FR_UND) { string_arg = Py_BuildValue("(s)", "%d-%b-%Y"); }
+ else if (freq_group == FR_HR) { string_arg = Py_BuildValue("(s)", "%d-%b-%Y %H:00"); }
+ else if (freq_group == FR_MIN) { string_arg = Py_BuildValue("(s)", "%d-%b-%Y %H:%M"); }
+ else if (freq_group == FR_SEC) { string_arg = Py_BuildValue("(s)", "%d-%b-%Y %H:%M:%S"); }
+
+ if (string_arg == NULL) { return NULL; }
+
+ retval = DateObject_strfmt(self, string_arg);
+ Py_DECREF(string_arg);
+
+ return retval;
+}
+
+static PyObject *
+DateObject_freqstr(DateObject *self, void *closure) {
+ PyObject *key = PyInt_FromLong(self->freq);
+ PyObject *freq_aliases = PyDict_GetItem(freq_dict, key);
+ PyObject *main_alias = PyTuple_GET_ITEM(freq_aliases, 0);
+ Py_DECREF(key);
+ Py_INCREF(main_alias);
+ return main_alias;
+}
+
+
+static PyObject *
+DateObject___repr__(DateObject* self)
+{
+ PyObject *py_str_rep, *py_freqstr, *py_repr;
+ char *str_rep, *freqstr, *repr;
+ int repr_len;
+
+ py_str_rep = DateObject___str__(self);
+ if (py_str_rep == NULL) { return NULL; }
+
+ py_freqstr = DateObject_freqstr(self, NULL);
+
+ str_rep = PyString_AsString(py_str_rep);
+ freqstr = PyString_AsString(py_freqstr);
+
+ repr_len = strlen(str_rep) + strlen(freqstr) + 6;
+
+ if((repr = malloc((repr_len + 1) * sizeof(char))) == NULL)
+ { return PyErr_NoMemory(); }
+
+ strcpy(repr, "<");
+ strcat(repr, freqstr);
+ strcat(repr, " : ");
+ strcat(repr, str_rep);
+ strcat(repr, ">");
+
+ py_repr = PyString_FromString(repr);
+
+ Py_DECREF(py_str_rep);
+ Py_DECREF(py_freqstr);
+
+ free(repr);
+
+ return py_repr;
+}
+
+/******************************
+ These methods seem rather useless. May or may not implement them.
+fromordinal(self, ordinal):
+ return Date(self.freq, datetime=dt.datetime.fromordinal(ordinal))
+tostring(self):
+ return str(self)
+toobject(self):
+ return self
+isvalid(self):
+ return True
+*******************************/
+
+
+static DateObject *
+DateObject_FromFreqAndValue(int freq, int value) {
+
+ DateObject *result = DateObject_New();
+
+ PyObject *args = PyTuple_New(0);
+ PyObject *kw = PyDict_New();
+ PyObject *py_freq = PyInt_FromLong(freq);
+ PyObject *py_value = PyInt_FromLong(value);
+
+ PyDict_SetItemString(kw, "freq", py_freq);
+ PyDict_SetItemString(kw, "value", py_value);
+
+ Py_DECREF(py_freq);
+ Py_DECREF(py_value);
+
+ DateObject_init(result, args, kw);
+
+ Py_DECREF(args);
+ Py_DECREF(kw);
+
+ return result;
+}
+
+static PyObject *
+DateObject_date_plus_int(PyObject *date, PyObject *pyint) {
+ DateObject *dateobj = (DateObject*)date;
+ if (DateObject_Check(pyint)) {
+ PyErr_SetString(PyExc_TypeError, "Cannot add two Date objects");
+ return NULL;
+ }
+
+ return (PyObject*)DateObject_FromFreqAndValue(dateobj->freq, PyInt_AsLong(pyint) + dateobj->value);
+}
+
+static PyObject *
+DateObject___add__(PyObject *left, PyObject *right)
+{
+ if (DateObject_Check(left)) {
+ return DateObject_date_plus_int(left, right);
+ } else {
+ return DateObject_date_plus_int(right, left);
+ }
+}
+
+static PyObject *
+DateObject___subtract__(PyObject *left, PyObject *right)
+{
+ int result;
+ DateObject *dleft;
+ if (!DateObject_Check(left)) {
+ PyErr_SetString(PyExc_ValueError, "Cannot subtract Date from non-Date value");
+ return NULL;
+ }
+
+ dleft = (DateObject*)left;
+
+ if (DateObject_Check(right)) {
+ DateObject *dright = (DateObject*)right;
+ if (dleft->freq != dright->freq) {
+ PyErr_SetString(PyExc_ValueError, "Cannot subtract Dates with different frequency");
+ return NULL;
+ }
+ result = dleft->value - dright->value;
+ return PyInt_FromLong(result);
+ } else {
+ result = dleft->value - PyInt_AsLong(right);
+ return (PyObject*)DateObject_FromFreqAndValue(dleft->freq, result);
+ }
+}
+
+static int
+DateObject___compare__(DateObject * obj1, DateObject * obj2)
+{
+ if (obj1->freq != obj2->freq) {
+ PyErr_SetString(PyExc_ValueError,
+ "Cannot compare dates with different frequency");
+ return -1;
+ }
+
+ if (obj1->value < obj2->value) return -1;
+ if (obj1->value > obj2->value) return 1;
+ if (obj1->value == obj2->value) return 0;
+
+}
+
+static long
+DateObject___hash__(DateObject *self)
+{
+ register int freq_group = get_freq_group(self->freq);
+
+ /* within a given frequency, hash values are guaranteed to be unique
+ for different dates. For different frequencies, we make a reasonable
+ effort to ensure hash values will be unique, but it is not guaranteed */
+ if (freq_group == FR_BUS) {
+ return self->value + 10000000;
+ } else if (freq_group == FR_WK) {
+ return self->value + 100000000;
+ } else { return self->value; }
+}
+
+static PyObject *
+DateObject___int__(DateObject *self)
+{
+ return PyInt_FromLong(self->value);
+}
+
+static PyObject *
+DateObject___float__(DateObject *self)
+{
+ return PyFloat_FromDouble((double)(self->value));
+}
+
+/***************************************************
+ ====== Date Properties ======
+****************************************************/
+
+// helper function for date property funcs
+static int
+DateObject_set_date_info(DateObject *self, struct date_info *dinfo) {
+ PyObject *daily_obj = DateObject_toordinal(self);
+ long absdate = PyInt_AsLong(daily_obj);
+
+ Py_DECREF(daily_obj);
+
+ if(dInfoCalc_SetFromAbsDate(dinfo, absdate,
+ GREGORIAN_CALENDAR)) return -1;
+
+ return 0;
+}
+
+// helper function for date property funcs
+static int
+DateObject_set_date_info_wtime(DateObject *self, struct date_info *dinfo) {
+ PyObject *daily_obj = DateObject_toordinal(self);
+ long absdate = PyInt_AsLong(daily_obj);
+ double abstime;
+
+ Py_DECREF(daily_obj);
+
+ abstime = getAbsTime(self->freq, absdate, self->value);
+
+ if(dInfoCalc_SetFromAbsDateTime(dinfo, absdate, abstime,
+ GREGORIAN_CALENDAR)) return -1;
+
+ return 0;
+}
+
+static PyObject *
+DateObject_year(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.year);
+}
+
+static PyObject *
+DateObject_quarter(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.quarter);
+}
+
+static PyObject *
+DateObject_month(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.month);
+}
+
+static PyObject *
+DateObject_day(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.day);
+}
+
+static PyObject *
+DateObject_day_of_week(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.day_of_week);
+}
+
+static PyObject *
+DateObject_day_of_year(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.day_of_year);
+}
+
+static PyObject *
+DateObject_week(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dInfoCalc_ISOWeek(&dinfo));
+}
+
+static PyObject *
+DateObject_hour(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info_wtime(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.hour);
+}
+
+static PyObject *
+DateObject_minute(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info_wtime(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong(dinfo.minute);
+}
+
+static PyObject *
+DateObject_second(DateObject *self, void *closure) {
+ struct date_info dinfo;
+ if(DateObject_set_date_info_wtime(self, &dinfo) == -1) return NULL;
+ return PyInt_FromLong((int)dinfo.second);
+}
+
+static PyObject *
+DateObject_datetime(DateObject *self, void *closure) {
+ PyObject *datetime;
+ struct date_info dinfo;
+ if(DateObject_set_date_info_wtime(self, &dinfo) == -1) return NULL;
+ datetime = PyDateTime_FromDateAndTime(dinfo.year, dinfo.month,
+ dinfo.day, dinfo.hour,
+ dinfo.minute, (int)dinfo.second, 0);
+ return datetime;
+}
+
+static int
+DateObject_ReadOnlyErr(DateObject *self, PyObject *value, void *closure) {
+ PyErr_SetString(PyExc_AttributeError, "Cannot set read-only property");
+ return -1;
+}
+
+static PyGetSetDef DateObject_getseters[] = {
+ {"year", (getter)DateObject_year, (setter)DateObject_ReadOnlyErr,
+ "Returns the year.", NULL},
+ {"quarter", (getter)DateObject_quarter, (setter)DateObject_ReadOnlyErr,
+ "Returns the quarter.", NULL},
+ {"month", (getter)DateObject_month, (setter)DateObject_ReadOnlyErr,
+ "Returns the month.", NULL},
+ {"week", (getter)DateObject_week, (setter)DateObject_ReadOnlyErr,
+ "Returns the week.", NULL},
+ {"day", (getter)DateObject_day, (setter)DateObject_ReadOnlyErr,
+ "Returns the day of month.", NULL},
+ {"day_of_week", (getter)DateObject_day_of_week, (setter)DateObject_ReadOnlyErr,
+ "Returns the day of week.", NULL},
+ {"day_of_year", (getter)DateObject_day_of_year, (setter)DateObject_ReadOnlyErr,
+ "Returns the day of year.", NULL},
+ {"second", (getter)DateObject_second, (setter)DateObject_ReadOnlyErr,
+ "Returns the second.", NULL},
+ {"minute", (getter)DateObject_minute, (setter)DateObject_ReadOnlyErr,
+ "Returns the minute.", NULL},
+ {"hour", (getter)DateObject_hour, (setter)DateObject_ReadOnlyErr,
+ "Returns the hour.", NULL},
+
+ {"freqstr", (getter)DateObject_freqstr, (setter)DateObject_ReadOnlyErr,
+ "Returns the string representation of frequency.", NULL},
+ {"datetime", (getter)DateObject_datetime, (setter)DateObject_ReadOnlyErr,
+ "Returns the Date object converted to standard python datetime object",
+ NULL},
+
+ {NULL} /* Sentinel */
+};
+
+
+static PyNumberMethods DateObject_as_number = {
+ (binaryfunc)DateObject___add__, /* nb_add */
+ (binaryfunc)DateObject___subtract__, /* nb_subtract */
+ 0, /* nb_multiply */
+ 0, /* nb_divide */
+ 0, /* nb_remainder */
+ 0, /* nb_divmod */
+ 0, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* nb_positive */
+ 0, /* nb_absolute */
+ 0, /* nb_nonzero */
+ 0, /* nb_invert */
+ 0, /* nb_lshift */
+ 0, /* nb_rshift */
+ 0, /* nb_and */
+ 0, /* nb_xor */
+ 0, /* nb_or */
+ 0, /* nb_coerce */
+ (unaryfunc)DateObject___int__, /* nb_int */
+ (unaryfunc)0, /* nb_long */
+ (unaryfunc)DateObject___float__, /* nb_float */
+ (unaryfunc)0, /* nb_oct */
+ (unaryfunc)0, /* nb_hex */
+};
+
+static PyMethodDef DateObject_methods[] = {
+ {"toordinal", (PyCFunction)DateObject_toordinal, METH_NOARGS,
+ DateObject_toordinal_doc},
+ {"strfmt", (PyCFunction)DateObject_strfmt, METH_VARARGS,
+ DateObject_strfmt_doc},
+ {"asfreq", (PyCFunction)DateObject_asfreq, METH_VARARGS | METH_KEYWORDS,
+ DateObject_asfreq_doc},
+ {NULL} /* Sentinel */
+};
+
+
+static PyTypeObject DateType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "timeseries.Date", /* tp_name */
+ sizeof(DateObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)DateObject_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)DateObject___compare__, /* tp_compare */
+ (reprfunc)DateObject___repr__, /* tp_repr */
+ &DateObject_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)DateObject___hash__, /* tp_hash */
+ 0, /* tp_call*/
+ (reprfunc)DateObject___str__, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | /* tp_flags */
+ Py_TPFLAGS_CHECKTYPES |
+ Py_TPFLAGS_BASETYPE,
+ "Defines a Date object, as the combination of a date and a frequency.\n"
+ "Several options are available to construct a Date object explicitly:\n\n"
+ "- Give appropriate values to the `year`, `month`, `day`, `quarter`, `hours`,\n"
+ " `minutes`, `seconds` arguments.\n\n"
+ " >>> td.Date(freq='Q',year=2004,quarter=3)\n"
+ " >>> td.Date(freq='D',year=2001,month=1,day=1)\n\n"
+ "- Use the `string` keyword. This method uses a modified version of the\n"
+ " mx.DateTime parser submodule. More information is available in its\n"
+ " documentation.\n\n"
+ " >>> ts.Date('D', '2007-01-01')\n\n"
+ "- Use the `datetime` keyword with an existing datetime.datetime object.\n\n"
+ " >>> td.Date('D', datetime=datetime.datetime.now())", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ DateObject_methods, /* tp_methods */
+ DateObject_members, /* tp_members */
+ DateObject_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DateObject_init, /* tp_init */
+ 0, /* tp_alloc */
+ DateObject_new, /* tp_new */
+};
+
+
+///////////////////////////////////////////////////////////////////////
+
+static char cseries_check_freq_doc[] =
+"translate user specified frequency into frequency constant";
+static PyObject *
+cseries_check_freq(PyObject *self, PyObject *args) {
+
+ PyObject *freq;
+ int freq_val;
+
+ if (!PyArg_ParseTuple(args, "O:check_freq(freq)", &freq)) return NULL;
+ if ((freq_val = check_freq(freq)) == INT_ERR_CODE) return NULL;
+
+ return PyInt_FromLong(freq_val);
+}
+
+static char cseries_check_freq_str_doc[] =
+"translate user specified frequency into standard string representation";
+static PyObject *
+cseries_check_freq_str(PyObject *self, PyObject *args) {
+
+ PyObject *alias_tuple, *result, *freq_key;
+ int freq_val;
+
+ if ((freq_key = cseries_check_freq(self, args)) == NULL) return NULL;
+
+ alias_tuple = PyDict_GetItem(freq_dict, freq_key);
+ result = PyTuple_GET_ITEM(alias_tuple, 0);
+
+ Py_INCREF(result);
+
+ Py_DECREF(freq_key);
+
+ return result;
+}
+
+static char cseries_thisday_doc[] =
+"Returns today's date, at the given frequency\n\n"
+":Parameters:\n"
+" - freq : string/int\n"
+" Frequency to convert the Date to. Accepts any valid frequency\n"
+" specification (string or integer)\n";
+static PyObject *
+cseries_thisday(PyObject *self, PyObject *args) {
+
+ PyObject *freq, *init_args, *init_kwargs;
+ time_t rawtime;
+ struct tm *timeinfo;
+ int freq_val;
+
+ DateObject *secondly_date;
+
+ if (!PyArg_ParseTuple(args, "O:thisday(freq)", &freq)) return NULL;
+
+ if ((freq_val = check_freq(freq)) == INT_ERR_CODE) return NULL;
+
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+
+ init_args = PyTuple_New(0);
+ init_kwargs = PyDict_New();
+
+ DICT_SETINT_STRKEY(init_kwargs, "freq", FR_SEC);
+ DICT_SETINT_STRKEY(init_kwargs, "year", timeinfo->tm_year+1900);
+ DICT_SETINT_STRKEY(init_kwargs, "month", timeinfo->tm_mon+1);
+ DICT_SETINT_STRKEY(init_kwargs, "day", timeinfo->tm_mday);
+ DICT_SETINT_STRKEY(init_kwargs, "hour", timeinfo->tm_hour);
+ DICT_SETINT_STRKEY(init_kwargs, "minute", timeinfo->tm_min);
+ DICT_SETINT_STRKEY(init_kwargs, "second", timeinfo->tm_sec);
+
+ secondly_date = DateObject_New();
+ DateObject_init(secondly_date, init_args, init_kwargs);
+
+ Py_DECREF(init_args);
+ Py_DECREF(init_kwargs);
+
+ if (freq_val != FR_SEC) {
+ DateObject *result = DateObject_New();
+
+ long (*asfreq_func)(long, char, struct asfreq_info*) = NULL;
+ struct asfreq_info af_info;
+
+ int date_val;
+
+ get_asfreq_info(FR_SEC, freq_val, &af_info);
+ asfreq_func = get_asfreq_func(FR_SEC, freq_val, 0);
+
+ date_val = asfreq_func(secondly_date->value, 'A', &af_info);
+
+ Py_DECREF(secondly_date);
+
+ result->freq = freq_val;
+ result->value = date_val;
+
+ return (PyObject*)result;
+
+ } else { return (PyObject*)secondly_date; }
+}
+
+
+static char TimeSeries_convert_doc[] = "";
+static PyObject *
+TimeSeries_convert(PyObject *self, PyObject *args)
+{
PyObject *arrayTest;
PyArrayObject *array, *newArray;
PyArrayObject *mask, *newMask;
@@ -1190,6 +2547,7 @@
npy_intp *dim, *newIdx;
long currPerLen;
char *position;
+ PyObject *fromFreq_arg, *toFreq_arg;
int fromFreq, toFreq;
char relation;
struct asfreq_info af_info;
@@ -1202,16 +2560,29 @@
returnVal = PyDict_New();
- if (!PyArg_ParseTuple(args, "OiislO:convert(array, fromfreq, tofreq, position, startIndex, mask)", &array, &fromFreq, &toFreq, &position, &startIndex, &mask)) return NULL;
+ if (!PyArg_ParseTuple(args,
+ "OOOslO:convert(array, fromfreq, tofreq, position, startIndex, mask)",
+ &array, &fromFreq_arg, &toFreq_arg,
+ &position, &startIndex, &mask)) return NULL;
+ if((fromFreq = check_freq(fromFreq_arg)) == INT_ERR_CODE) return NULL;
+ if((toFreq = check_freq(toFreq_arg)) == INT_ERR_CODE) return NULL;
+
if (toFreq == fromFreq)
{
- PyDict_SetItemString(returnVal, "values", (PyObject*)array);
- PyDict_SetItemString(returnVal, "mask", (PyObject*)mask);
+ PyObject *sidx;
+ newArray = (PyArrayObject *)PyArray_Copy(array);
+ newMask = (PyArrayObject *)PyArray_Copy(mask);
+ sidx = PyInt_FromLong(startIndex);
- Py_DECREF(array);
- Py_DECREF(mask);
+ PyDict_SetItemString(returnVal, "values", (PyObject*)newArray);
+ PyDict_SetItemString(returnVal, "mask", (PyObject*)newMask);
+ PyDict_SetItemString(returnVal, "startindex", sidx);
+ Py_DECREF(newArray);
+ Py_DECREF(newMask);
+ Py_DECREF(sidx);
+
return returnVal;
}
@@ -1338,9 +2709,9 @@
return returnVal;
}
-static char cseries_asfreq_doc[] = "";
+static char DateArray_asfreq_doc[] = "";
static PyObject *
-cseries_asfreq(PyObject *self, PyObject *args)
+DateArray_asfreq(PyObject *self, PyObject *args)
{
PyArrayObject *fromDates, *toDates;
PyArrayIterObject *iterFrom, *iterTo;
@@ -1351,7 +2722,9 @@
long (*asfreq_main)(long, char, struct asfreq_info*) = NULL;
struct asfreq_info af_info;
- if (!PyArg_ParseTuple(args, "Oiis:asfreq(fromDates, fromfreq, tofreq, relation)", &fromDates, &fromFreq, &toFreq, &relation)) return NULL;
+ if (!PyArg_ParseTuple(args,
+ "Oiis:asfreq(fromDates, fromfreq, tofreq, relation)",
+ &fromDates, &fromFreq, &toFreq, &relation)) return NULL;
get_asfreq_info(fromFreq, toFreq, &af_info);
@@ -1388,45 +2761,9 @@
}
-static int dInfo_year(struct date_info *dateObj) { return dateObj->year; }
-static int dInfo_quarter(struct date_info *dateObj) { return dateObj->quarter; }
-static int dInfo_month(struct date_info *dateObj) { return dateObj->month; }
-static int dInfo_day(struct date_info *dateObj) { return dateObj->day; }
-static int dInfo_day_of_year(struct date_info *dateObj) { return dateObj->day_of_year; }
-static int dInfo_day_of_week(struct date_info *dateObj) { return dateObj->day_of_week; }
-static int dInfo_week(struct date_info *dateObj) { return dInfoCalc_ISOWeek(dateObj); }
-static int dInfo_hour(struct date_info *dateObj) { return dateObj->hour; }
-static int dInfo_minute(struct date_info *dateObj) { return dateObj->minute; }
-static int dInfo_second(struct date_info *dateObj) { return (int)dateObj->second; }
-
-static double getAbsTime(int freq, long dailyDate, long originalDate) {
-
- long startOfDay, periodsPerDay;
-
- switch(freq)
- {
- case FR_HR:
- periodsPerDay = 24;
- break;
- case FR_MIN:
- periodsPerDay = 24*60;
- break;
- case FR_SEC:
- periodsPerDay = 24*60*60;
- break;
- default:
- return 0;
- }
-
- startOfDay = asfreq_DtoHIGHFREQ(dailyDate, 'B', periodsPerDay);
- return (24*60*60)*((double)(originalDate - startOfDay))/((double)periodsPerDay);
-}
-
-
-
-static char cseries_getDateInfo_doc[] = "";
+static char DateArray_getDateInfo_doc[] = "";
static PyObject *
-cseries_getDateInfo(PyObject *self, PyObject *args)
+DateArray_getDateInfo(PyObject *self, PyObject *args)
{
int freq;
char *info;
@@ -1513,162 +2850,50 @@
return (PyObject *) newArray;
}
-static char *str_replace(const char *s, const char *old, const char *new)
-{
- char *ret;
- int i, count = 0;
- size_t newlen = strlen(new);
- size_t oldlen = strlen(old);
+static PyMethodDef cseries_methods[] = {
- for (i = 0; s[i] != '\0'; i++) {
- if (strstr(&s[i], old) == &s[i]) {
- count++;
- i += oldlen - 1;
- }
- }
+ {"TS_convert", TimeSeries_convert, METH_VARARGS, TimeSeries_convert_doc},
- ret = malloc(i + 1 + count * (newlen - oldlen));
- if (ret == NULL) return NULL;
+ {"DA_asfreq", DateArray_asfreq, METH_VARARGS, DateArray_asfreq_doc},
+ {"DA_getDateInfo", DateArray_getDateInfo, METH_VARARGS, DateArray_getDateInfo_doc},
- i = 0;
- while (*s) {
- if (strstr(s, old) == s) {
- strcpy(&ret[i], new);
- i += newlen;
- s += oldlen;
- } else {
- ret[i++] = *s++;
- }
- }
- ret[i] = '\0';
+ {"thisday", cseries_thisday, METH_VARARGS, cseries_thisday_doc},
+ {"check_freq", cseries_check_freq, METH_VARARGS, cseries_check_freq_doc},
+ {"check_freq_str", cseries_check_freq_str, METH_VARARGS, cseries_check_freq_str_doc},
- return ret;
-}
+ {"set_callback_DateFromString", set_callback_DateFromString, METH_VARARGS,
+ set_callback_DateFromString_doc},
+ {"set_callback_DateTimeFromString", set_callback_DateTimeFromString, METH_VARARGS,
+ set_callback_DateTimeFromString_doc},
-static char cseries_strfmt_doc[] = "";
-static PyObject *
-cseries_strfmt(PyObject *self, PyObject *args)
-{
-
- char *orig_fmt_str, *fmt_str, *q_loc;
- char *result;
- char place_holder[] = "^`";
- struct tm c_date;
- struct date_info tempDate;
- int result_len;
- PyObject *date, *py_result;
-
- if (!PyArg_ParseTuple(args, "Os:strfmt(datetime, fmt_str)", &date, &orig_fmt_str)) return NULL;
-
- if (dInfoCalc_SetFromDateAndTime(&tempDate,
- PyDateTime_GET_YEAR(date),
- PyDateTime_GET_MONTH(date),
- PyDateTime_GET_DAY(date),
- PyDateTime_DATE_GET_HOUR(date),
- PyDateTime_DATE_GET_MINUTE(date),
- PyDateTime_DATE_GET_SECOND(date),
- GREGORIAN_CALENDAR)) return NULL;
-
- /* We need to modify the fmt_str passed in to handle our special syntax for quarters.
- We can't modify the string passed in directly, so we must make a copy. */
- fmt_str = malloc((strlen(orig_fmt_str) + 1)*sizeof(char));
- strcpy(fmt_str, orig_fmt_str);
-
- if ((q_loc = strstr(fmt_str,"%q")) != NULL) {
- q_loc = strstr(fmt_str,"%q");
- strncpy (q_loc,place_holder,2);
- }
-
- c_date.tm_sec = (int)tempDate.second;
- c_date.tm_min = tempDate.minute;
- c_date.tm_hour = tempDate.hour;
- c_date.tm_mday = tempDate.day;
- c_date.tm_mon = tempDate.month - 1;
- c_date.tm_year = tempDate.year - 1900;
- c_date.tm_wday = tempDate.day_of_week;
- c_date.tm_yday = tempDate.day_of_year;
- c_date.tm_isdst = -1;
-
- result_len = strlen(orig_fmt_str) + 50;
-
- result = malloc(result_len * sizeof(char));
-
- strftime(result, result_len, fmt_str, &c_date);
-
- if (q_loc != NULL) {
- char *alt_result;
- char q_str[2];
-
- sprintf(q_str, "%i", tempDate.quarter);
- alt_result = str_replace(result, place_holder, q_str);
- py_result = PyString_FromString(alt_result);
- free(result);
- free(alt_result);
- } else {
- py_result = PyString_FromString(result);
- free(result);
- }
-
- return py_result;
-
-}
-
-
-///////////////////////////////////////////////////////////////////////
-
-//{"fpointer", cseries_fpointer, METH_VARARGS, cseries_fpointer_doc},
-
-static PyMethodDef cseries_methods[] = {
- {"strfmt", cseries_strfmt, METH_VARARGS, cseries_strfmt_doc},
- {"convert", cseries_convert, METH_VARARGS, cseries_convert_doc},
- {"asfreq", cseries_asfreq, METH_VARARGS, cseries_asfreq_doc},
- {"getDateInfo", cseries_getDateInfo, METH_VARARGS, cseries_getDateInfo_doc},
{NULL, NULL}
};
PyMODINIT_FUNC
initcseries(void)
{
- PyObject *m, *TSER_CONSTANTS;
+ PyObject *m;
+
+ if (PyType_Ready(&DateType) < 0) return;
+
m = Py_InitModule3("cseries", cseries_methods, cseries_doc);
+ if (m == NULL)
+ return;
+
import_array();
PyDateTime_IMPORT;
- TSER_CONSTANTS = PyDict_New();
+ Py_INCREF(&DateType);
+ PyModule_AddObject(m, "Date", (PyObject *)&DateType);
- // Add all the frequency constants to a python dictionary
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANN", FR_ANN);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNJAN", FR_ANNJAN);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNFEB", FR_ANNFEB);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNMAR", FR_ANNMAR);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNAPR", FR_ANNAPR);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNMAY", FR_ANNMAY);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNJUN", FR_ANNJUN);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNJUL", FR_ANNJUL);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNAUG", FR_ANNAUG);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNSEP", FR_ANNSEP);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNOCT", FR_ANNOCT);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNNOV", FR_ANNNOV);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_ANNDEC", FR_ANNDEC);
+ if(build_freq_dict(m) == INT_ERR_CODE) {
+ PyErr_SetString( \
+ PyExc_ImportError, \
+ "initialization of module timeseries.cseries failed");
+ return;
+ };
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_QTR", FR_QTR);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_MTH", FR_MTH);
-
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WK", FR_WK);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WKSUN", FR_WKSUN);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WKSAT", FR_WKSAT);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WKFRI", FR_WKFRI);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WKTHU", FR_WKTHU);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WKWED", FR_WKWED);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WKTUE", FR_WKTUE);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_WKMON", FR_WKMON);
-
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_BUS", FR_BUS);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_DAY", FR_DAY);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_HR", FR_HR);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_MIN", FR_MIN);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_SEC", FR_SEC);
- ADD_INT_TO_DICT(TSER_CONSTANTS, "FR_UND", FR_UND);
-
- PyModule_AddObject(m, "TSER_CONSTANTS", TSER_CONSTANTS);
+ PyModule_AddObject(m, "freq_dict", freq_dict);
+ PyModule_AddObject(m, "freq_dict_rev", freq_dict_rev);
+ PyModule_AddObject(m, "freq_constants", freq_constants);
}
\ No newline at end of file
Modified: trunk/Lib/sandbox/timeseries/tcore.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tcore.py 2007-03-20 14:42:18 UTC (rev 2851)
+++ trunk/Lib/sandbox/timeseries/tcore.py 2007-03-20 14:44:08 UTC (rev 2852)
@@ -13,19 +13,8 @@
import numpy
import numpy.core.numeric as numeric
-from scipy.interpolate import fitpack
-
import maskedarray as MA
-from cseries import TSER_CONSTANTS
-
-"""add constants in cfame.FAME_CONSTANTS dictionary to global namespace
-for this module"""
-
-_g = globals()
-_g.update(TSER_CONSTANTS)
-
-
#####---------------------------------------------------------------------------
#---- --- Generic functions ---
#####---------------------------------------------------------------------------
@@ -48,149 +37,6 @@
#####---------------------------------------------------------------------------
-#---- --- Option conversion ---
-#####---------------------------------------------------------------------------
-fmtobs_dict = {'UNDEFINED': ['UNDEF','UNDEFINED',None],
- 'BEGINNING': ['BEGIN','BEGINNING'],
- 'ENDING': ['END','ENDING'],
- 'AVERAGED': ['AVERAGE','AVERAGE','MEAN'],
- 'SUMMED': ['SUM','SUMMED'],
- 'MAXIMUM': ['MAX','MAXIMUM','HIGH'],
- 'MINIMUM': ['MIN','MINIMUM','LOW']}
-
-obs_dict = {None:None,
- "UNDEFINED":None,
- "UNDEF":None,
- "BEGIN": first_unmasked_val,
- "BEGINNING": first_unmasked_val,
- "END": last_unmasked_val,
- "ENDING": last_unmasked_val,
- "AVERAGED": MA.average,
- "AVERAGE": MA.average,
- "MEAN": MA.average,
- "SUMMED": MA.sum,
- "SUM": MA.sum,
- "MAXIMUM": MA.maximum,
- "MAX": MA.maximum,
- "MINIMUM": MA.minimum,
- "MIN": MA.minimum,
- }
-obsDict = obs_dict
-fmtobs_revdict = reverse_dict(fmtobs_dict)
-
-#
-def fmtObserv(obStr):
- "Converts a possible 'Observed' string into acceptable values."
- if obStr is None:
- return fmtobs_revdict[None]
- elif obStr.upper() in fmtobs_revdict:
- return fmtobs_revdict[obStr.upper()]
- else:
- raise ValueError("Invalid value for observed attribute: %s " % str(obStr))
-
-_weekly_prefixes = ['W','WEEK','WEEKLY']
-_week_end_map = {
- FR_WKSUN:'SUNDAY',
- FR_WKSAT:'SATURDAY',
- FR_WKFRI:'FRIDAY',
- FR_WKTHU:'THURSDAY',
- FR_WKWED:'WEDNESDAY',
- FR_WKTUE:'TUESDAY',
- FR_WKMON:'MONDAY'}
-
-def _gen_weekly_strs(day):
- result = []
- for pr in _weekly_prefixes:
- result += [pr+'-'+day_str for day_str in (day[:3], day)]
- return result
-
-_annual_prefixes = ['A','Y','ANNUAL','ANNUALLY','YEAR','YEARLY']
-_year_end_map = {
- FR_ANNJAN:'JANUARY',
- FR_ANNFEB:'FEBRUARY',
- FR_ANNMAR:'MARCH',
- FR_ANNAPR:'APRIL',
- FR_ANNMAY:'MAY',
- FR_ANNJUN:'JUNE',
- FR_ANNJUL:'JULY',
- FR_ANNAUG:'AUGUST',
- FR_ANNSEP:'SEPTEMBER',
- FR_ANNOCT:'OCTOBER',
- FR_ANNNOV:'NOVEMBER',
- FR_ANNDEC:'DECEMBER'
- }
-
-def _gen_annual_strs(month):
- result = []
- for pr in _annual_prefixes:
- result += [pr+'-'+mth_str for mth_str in (month[:3], month)]
- return result
-
-freq_dict = { FR_QTR: ['Q','QUARTER','QUARTERLY'],
- FR_MTH: ['M','MONTH','MONTHLY'],
- FR_BUS: ['B','BUSINESS','BUSINESSLY'],
- FR_DAY: ['D','DAY','DAILY'],
- FR_HR: ['H','HOUR','HOURLY'],
- FR_MIN: ['T','MINUTE','MINUTELY'],
- FR_SEC: ['S','SECOND','SECONDLY'],
- FR_UND: ['U','UNDEF','UNDEFINED']
- }
-
-for _freq, day_str in _week_end_map.iteritems():
- freq_dict[_freq] = _gen_weekly_strs(day_str)
-freq_dict[FR_WK] += _weekly_prefixes
-
-for _freq, mth_str in _year_end_map.iteritems():
- freq_dict[_freq] = _gen_annual_strs(mth_str)
-freq_dict[FR_ANN] += _annual_prefixes
-
-freq_revdict = reverse_dict(freq_dict)
-
-def freq_fromstr(freq_asstr):
- "Converts a frequency given as string to the corresponding integer."
- freq_asstr = freq_asstr.upper()
- if freq_asstr not in freq_revdict.keys():
- raise ValueError, "Invalid frequency string %s" % freq_asstr
- return freq_revdict[freq_asstr]
-
-def freq_tostr(freq_asint):
- "Converts a frequency given as integer to the corresponding symbol."
- if freq_asint not in freq_dict.keys():
- raise ValueError, "Invalid frequency representation %s" % freq_asint
- return freq_dict[freq_asint][0]
-
-def check_freq(freq):
- "Converts a possible 'frequency' string to acceptable values."
- if freq is None:
- return None
- elif isinstance(freq, int):
- if freq not in freq_dict.keys():
- raise ValueError("Invalid frequency: %s " % str(freq))
- return freq
- elif freq.upper() in freq_revdict.keys():
- return freq_revdict[freq.upper()]
- else:
- raise ValueError("Invalid frequency: %s " % str(freq))
-
-def check_freqstr(freq):
- if freq is None:
- return None
- elif isinstance(freq, int):
- if freq not in freq_dict.keys():
- raise ValueError("Invalid frequency: %s " % str(freq))
- return freq_dict[freq][0]
- elif freq.upper() in freq_revdict.keys():
- return freq_dict[freq_revdict[freq.upper()]][0]
- else:
- raise ValueError("Invalid frequency: %s " % str(freq))
-fmtFreq = check_freqstr
-
-def get_freq_group(freq):
- # truncate frequency to nearest thousand
- return (freq//1000)*1000
-
-
-#####---------------------------------------------------------------------------
#---- --- Misc functions ---
#####---------------------------------------------------------------------------
#http://aspn.activestate.com/ASPN/Mail/Message/python-tutor/2302348
@@ -203,11 +49,10 @@
yield f
else:
yield elm
-
+
def flatargs(*args):
"Flattens the arguments."
if not hasattr(args, '__iter__'):
return args
else:
return flatten_sequence(args)
-
Modified: trunk/Lib/sandbox/timeseries/tdates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tdates.py 2007-03-20 14:42:18 UTC (rev 2851)
+++ trunk/Lib/sandbox/timeseries/tdates.py 2007-03-20 14:44:08 UTC (rev 2852)
@@ -27,38 +27,25 @@
import maskedarray as MA
-try:
- from mx.DateTime import DateTimeType
-except ImportError:
- class DateTimeType: pass
+from parser import DateFromString, DateTimeFromString
-from parser import DateFromString, DateTimeFromString
-
import tcore as corelib
-import tcore as _c
+import const as _c
import cseries
+from cseries import Date, thisday, check_freq, check_freq_str
+today = thisday
-
__all__ = [
'Date', 'DateArray','isDate','isDateArray',
'DateError', 'ArithmeticDateError', 'FrequencyDateError','InsufficientDateError',
'datearray','date_array', 'date_array_fromlist', 'date_array_fromrange',
-'day_of_week','day_of_year','day','month','quarter','year','hour','minute','second',
-'truncateDate','monthToQuarter','thisday','today','prevbusday','asfreq',
-'period_break'
+'day_of_week','day_of_year','day','month','quarter','year','hour','minute',
+'second','thisday','today','prevbusday','period_break', 'check_freq',
+'check_freq_str'
]
-#####---------------------------------------------------------------------------
-#---- --- Date Info ---
-#####---------------------------------------------------------------------------
-OriginDate = dt.datetime(1970, 1, 1)
-secondlyOriginDate = OriginDate - dt.timedelta(seconds=1)
-minutelyOriginDate = OriginDate - dt.timedelta(minutes=1)
-hourlyOriginDate = OriginDate - dt.timedelta(hours=1)
-
-
#####---------------------------------------------------------------------------
#---- --- Date Exceptions ---
#####---------------------------------------------------------------------------
@@ -72,15 +59,15 @@
"Calculate the string representation"
return str(self.args)
__repr__ = __str__
-
+
class InsufficientDateError(DateError):
- """Defines the exception raised when there is not enough information
+ """Defines the exception raised when there is not enough information
to create a Date object."""
def __init__(self, msg=None):
if msg is None:
msg = "Insufficient parameters given to create a date at the given frequency"
DateError.__init__(self, msg)
-
+
class FrequencyDateError(DateError):
"""Defines the exception raised when the frequencies are incompatible."""
def __init__(self, msg, freql=None, freqr=None):
@@ -88,470 +75,45 @@
if not (freql is None or freqr is None):
msg += " (%s<>%s)" % (freql, freqr)
DateError.__init__(self, msg)
-
+
class ArithmeticDateError(DateError):
"""Defines the exception raised when dates are used in arithmetic expressions."""
def __init__(self, msg=''):
msg += " Cannot use dates for arithmetics!"
DateError.__init__(self, msg)
-#####---------------------------------------------------------------------------
-#---- --- Date Class ---
-#####---------------------------------------------------------------------------
-class Date:
- """Defines a Date object, as the combination of a date and a frequency.
- Several options are available to construct a Date object explicitly:
-
- - Give appropriate values to the `year`, `month`, `day`, `quarter`, `hours`,
- `minutes`, `seconds` arguments.
-
- >>> td.Date(freq='Q',year=2004,quarter=3)
- >>> td.Date(freq='D',year=2001,month=1,day=1)
-
- - Use the `string` keyword. This method calls the `mx.DateTime.Parser`
- submodule, more information is available in its documentation.
-
- >>> ts.Date('D', '2007-01-01')
-
- - Use the `datetime` keyword with an existing datetime.datetime object.
-
- >>> td.Date('D', datetime=datetime.datetime.now())
- """
- default_fmtstr = {_c.FR_ANN: "%Y",
- _c.FR_QTR: "%YQ%q",
- _c.FR_MTH: "%b-%Y",
- _c.FR_WK: "%d-%b-%Y",
- _c.FR_BUS: "%d-%b-%Y",
- _c.FR_DAY: "%d-%b-%Y",
- _c.FR_UND: "%d-%b-%Y",
- _c.FR_HR: "%d-%b-%Y %H:00",
- _c.FR_MIN: "%d-%b-%Y %H:%M",
- _c.FR_SEC: "%d-%b-%Y %H:%M:%S"
- }
-
- for x in range(7): default_fmtstr[_c.FR_WK+x] = default_fmtstr[_c.FR_WK]
- for x in range(12): default_fmtstr[_c.FR_ANN+x] = default_fmtstr[_c.FR_ANN]
-
- def __init__(self, freq, value=None, string=None,
- year=None, month=None, day=None, quarter=None,
- hour=None, minute=None, second=None,
- datetime=None):
-
- if hasattr(freq, 'freq'):
- self.freq = corelib.check_freq(freq.freq)
- else:
- self.freq = corelib.check_freq(freq)
- self.freqstr = corelib.freq_tostr(self.freq)
-
- _freqGroup = corelib.get_freq_group(self.freq)
-
- if isinstance(value, str):
- if self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
- self.datetime = DateTimeFromString(value)
- else:
- self.datetime = DateFromString(value)
- elif value is not None:
-
- #value could be a numpy scalar, which is not acceptable
- value = int(value)
-
- if self.freq == _c.FR_SEC:
- self.datetime = secondlyOriginDate + dt.timedelta(seconds=value)
- elif self.freq == _c.FR_MIN:
- self.datetime = minutelyOriginDate + dt.timedelta(minutes=value)
- elif self.freq == _c.FR_HR:
- self.datetime = hourlyOriginDate + dt.timedelta(hours=value)
- elif self.freq == _c.FR_DAY:
- self.datetime = dt.datetime.fromordinal(value)
- elif self.freq == _c.FR_UND:
- self.datetime = int(value)
- elif self.freq == _c.FR_BUS:
- valtmp = (value - 1)//5
- self.datetime = dt.datetime.fromordinal(value + valtmp*2)
- elif _freqGroup == _c.FR_WK:
- """value=1 must correspond to first FULL week in the year 0001
- ending on the given day of the week"""
- self.datetime = dt.datetime(1,1,7) + \
- dt.timedelta(days=(value-1)*7 + (self.freq - _c.FR_WK))
- elif self.freq == _c.FR_MTH:
- year = (value - 1)//12 + 1
- month = value - (year - 1)*12
- self.datetime = dt.datetime(year, month, 1)
- elif self.freq == _c.FR_QTR:
- year = (value - 1)//4 + 1
- month = (value - (year - 1)*4)*3
- self.datetime = dt.datetime(year, month, 1)
- elif _freqGroup == _c.FR_ANN:
- if self.freq == _c.FR_ANNDEC:
- self.datetime = dt.datetime(value, 12, 1)
- else:
- self.datetime = dt.datetime(value, self.freq - _c.FR_ANN, 1)
- else:
- raise ValueError("unrecognized frequency: "+str(self.freq))
-
- elif string is not None:
- if self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
- self.datetime = DateTimeFromString(string)
- else:
- self.datetime = DateFromString(string)
-
- elif datetime is not None:
- if isinstance(datetime, DateTimeType):
- datetime = mx_to_datetime(datetime)
- self.datetime = truncateDate(self.freq, datetime)
-
- else:
- # First, some basic checks.....
- if year is None:
- raise InsufficientDateError
- if _freqGroup in (_c.FR_BUS, _c.FR_DAY, _c.FR_WK, _c.FR_UND):
- if month is None or day is None:
- raise InsufficientDateError
- elif self.freq == _c.FR_MTH:
- if month is None:
- raise InsufficientDateError
- day = 1
- elif self.freq == _c.FR_QTR:
- if quarter is None:
- raise InsufficientDateError
- month = quarter * 3
- day = 1
- elif _freqGroup == _c.FR_ANN:
- month = self.freq - _freqGroup
- if month == 0: month = 12
- day = 1
- elif self.freq == _c.FR_SEC:
- if month is None or day is None or second is None:
- raise InsufficientDateError
-
- if _freqGroup in (_c.FR_BUS, _c.FR_DAY, _c.FR_WK,
- _c.FR_MTH, _c.FR_QTR, _c.FR_ANN):
- self.datetime = truncateDate(self.freq, dt.datetime(year, month, day))
- if self.freq == _c.FR_BUS:
- if self.datetime.isoweekday() in [6,7]:
- raise ValueError("Weekend passed as business day")
- elif self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
- if hour is None:
- if minute is None:
- if second is None:
- hour = 0
- else:
- hour = second//3600
- else:
- hour = minute // 60
- if minute is None:
- if second is None:
- minute = 0
- else:
- minute = (second-hour*3600)//60
- if second is None:
- second = 0
- else:
- second = second % 60
- self.datetime = truncateDate(self.freq,
- dt.datetime(year, month, day,
- hour, minute, second))
- else:
- raise ValueError("unrecognized frequency: "+str(self.freq))
-
- self.value = self.__value()
-
- def __getitem__(self, indx):
- return self
-
- @property
- def day(self):
- "Returns the day of month."
- return self.__getdateinfo__('D')
- @property
- def day_of_week(self):
- "Returns the day of week."
- return self.__getdateinfo__('W')
- @property
- def day_of_year(self):
- "Returns the day of year."
- return self.__getdateinfo__('R')
- @property
- def month(self):
- "Returns the month."
- return self.__getdateinfo__('M')
- @property
- def quarter(self):
- "Returns the quarter."
- return self.__getdateinfo__('Q')
- @property
- def year(self):
- "Returns the year."
- return self.__getdateinfo__('Y')
- @property
- def second(self):
- "Returns the seconds."
- return self.__getdateinfo__('S')
- @property
- def minute(self):
- "Returns the minutes."
- return self.__getdateinfo__('T')
- @property
- def hour(self):
- "Returns the hour."
- return self.__getdateinfo__('H')
- @property
- def week(self):
- "Returns the week."
- return self.__getdateinfo__('I')
-
- def __getdateinfo__(self, info):
- return int(cseries.getDateInfo(numpy.asarray(self.value),
- self.freq, info))
- __getDateInfo = __getdateinfo__
-
- def __add__(self, other):
- if isinstance(other, Date):
- raise FrequencyDateError("Cannot add dates",
- self.freqstr, other.freqstr)
- return Date(freq=self.freq, value=int(self) + other)
-
- def __radd__(self, other):
- return self+other
-
- def __sub__(self, other):
- if isinstance(other, Date):
- if self.freq != other.freq:
- raise FrequencyDateError("Cannot subtract dates", \
- self.freqstr, other.freqstr)
- else:
- return int(self) - int(other)
- else:
- return self + (-1) * int(other)
-
- def __eq__(self, other):
- if not hasattr(other, 'freq'):
- return False
- elif self.freq != other.freq:
- raise FrequencyDateError("Cannot compare dates", \
- self.freqstr, other.freqstr)
- return int(self) == int(other)
-
- def __cmp__(self, other):
- if not hasattr(other, 'freq'):
- return False
- elif self.freq != other.freq:
- raise FrequencyDateError("Cannot compare dates", \
- self.freqstr, other.freqstr)
- return int(self)-int(other)
-
- def __hash__(self):
- return hash(int(self)) ^ hash(self.freq)
-
- def __int__(self):
- return self.value
-
- def __float__(self):
- return float(self.value)
-
- def __value(self):
- "Converts the date to an integer, depending on the current frequency."
- _freqGroup = corelib.get_freq_group(self.freq)
- # Secondly......
- if self.freq == _c.FR_SEC:
- delta = (self.datetime - secondlyOriginDate)
- val = delta.days*86400 + delta.seconds
- # Minutely......
- elif self.freq == _c.FR_MIN:
- delta = (self.datetime - minutelyOriginDate)
- val = delta.days*1440 + delta.seconds/(60)
- # Hourly........
- elif self.freq == _c.FR_HR:
- delta = (self.datetime - hourlyOriginDate)
- val = delta.days*24 + delta.seconds/(3600)
- # Daily
- elif self.freq == _c.FR_DAY:
- val = self.datetime.toordinal()
- # undefined
- elif self.freq == _c.FR_UND:
- if not hasattr(self.datetime, 'toordinal'):
- val = self.datetime
- else:
- val = self.datetime.toordinal()
- # Business days.
- elif self.freq == _c.FR_BUS:
- days = self.datetime.toordinal()
- weeks = days // 7
- val = days - weeks*2
- # Weekly........
- elif _freqGroup == _c.FR_WK:
- val = self.datetime.toordinal()//7
- # Monthly.......
- elif self.freq == _c.FR_MTH:
- val = (self.datetime.year-1)*12 + self.datetime.month
- # Quarterly.....
- elif self.freq == _c.FR_QTR:
- val = (self.datetime.year-1)*4 + self.datetime.month//3
- # Annual .......
- elif _freqGroup == _c.FR_ANN:
- val = self.datetime.year
-
- return int(val)
- #......................................................
- def strfmt(self, fmt):
- "Formats the date"
- if fmt is None:
- fmt = self.default_fmtstr[self.freq]
- if self.freq == _c.FR_UND:
- return str(self.value)
- return cseries.strfmt(self.datetime, fmt)
-
- def __str__(self):
- return self.strfmt(self.default_fmtstr[self.freq])
-
- def __repr__(self):
- return "<%s : %s>" % (str(self.freqstr), str(self))
- #......................................................
- def toordinal(self):
- "Returns the date as an ordinal."
- # FIXME: We shouldn't need the test if we were in C
- if self.freq == _c.FR_UND:
- return self.value
- return self.datetime.toordinal()
-
- def fromordinal(self, ordinal):
- "Returns the date as an ordinal."
- return Date(self.freq, datetime=dt.datetime.fromordinal(ordinal))
-
- def tostring(self):
- "Returns the date as a string."
- return str(self)
-
- def toobject(self):
- "Returns the date as itself."
- return self
-
- def isvalid(self):
- "Returns whether the DateArray is valid: no missing/duplicated dates."
- # A date is always valid by itself, but we need the object to support the function
- # when we're working with singletons.
- return True
- #......................................................
-
-
#####---------------------------------------------------------------------------
#---- --- Functions ---
#####---------------------------------------------------------------------------
-def mx_to_datetime(mxDate):
- microsecond = 1000000*(mxDate.second % 1)
- return dt.datetime(mxDate.year, mxDate.month,
- mxDate.day, mxDate.hour,
- mxDate.minute,
- int(mxDate.second), microsecond)
-
-
-def truncateDate(freq, datetime):
- "Chops off the irrelevant information from the datetime object passed in."
- freq = corelib.check_freq(freq)
- _freqGroup = corelib.get_freq_group(freq)
- if freq == _c.FR_MIN:
- return dt.datetime(datetime.year, datetime.month, datetime.day, \
- datetime.hour, datetime.minute)
- elif freq == _c.FR_HR:
- return dt.datetime(datetime.year, datetime.month, datetime.day, \
- datetime.hour)
- elif freq in (_c.FR_BUS, _c.FR_DAY):
- if freq == _c.FR_BUS and datetime.isoweekday() in (6,7):
- raise ValueError("Weekend passed as business day")
- return dt.datetime(datetime.year, datetime.month, datetime.day)
- elif _freqGroup == _c.FR_WK:
- d = datetime.toordinal()
- day_adj = (7 - (freq - _c.FR_WK)) % 7
- return dt.datetime.fromordinal(d + ((7 - day_adj) - d % 7) % 7)
- elif freq == _c.FR_MTH:
- return dt.datetime(datetime.year, datetime.month, 1)
- elif freq == _c.FR_QTR:
- return dt.datetime(datetime.year, monthToQuarter(datetime.month)*3, 1)
- elif _freqGroup == _c.FR_ANN:
-
- if freq == _c.FR_ANNDEC: fr_month = 12
- else: fr_month = freq - _c.FR_ANN
-
- if datetime.month <= fr_month:
- return dt.datetime(datetime.year, fr_month, 1)
- else:
- return dt.datetime(datetime.year+1, fr_month, 1)
-
- else:
- return datetime
-
-def monthToQuarter(monthNum):
- """Returns the quarter corresponding to the month `monthnum`.
- For example, December is the 4th quarter, Januray the first."""
- return int((monthNum-1)/3)+1
-
-def thisday(freq):
- "Returns today's date, at the given frequency `freq`."
- freq = corelib.check_freq(freq)
- _freqGroup = corelib.get_freq_group(freq)
- tempDate = dt.datetime.now()
- # if it is Saturday or Sunday currently, freq==B, then we want to use Friday
- if freq == _c.FR_BUS and tempDate.isoweekday() >= 6:
- tempDate = tempDate - dt.timedelta(days=(tempDate.isoweekday() - 5))
- return Date(freq=freq, datetime=tempDate)
-today = thisday
-
def prevbusday(day_end_hour=18, day_end_min=0):
"Returns the previous business day."
tempDate = dt.datetime.now()
dateNum = tempDate.hour + float(tempDate.minute)/60
checkNum = day_end_hour + float(day_end_min)/60
- if dateNum < checkNum:
+ if dateNum < checkNum:
return thisday(_c.FR_BUS) - 1
- else:
+ else:
return thisday(_c.FR_BUS)
-
-def asfreq(date, toFreq, relation="BEFORE"):
- """Returns a date converted to another frequency `toFreq`, according to the
- relation `relation` ."""
- tofreq = corelib.check_freq(toFreq)
- _rel = relation.upper()[0]
- if _rel not in ['B', 'A']:
- msg = "Invalid relation '%s': Should be in ['before', 'after']"
- raise ValueError, msg % relation
- if not isinstance(date, Date):
- raise DateError, "Date should be a valid Date instance!"
- if date.freq == _c.FR_UND:
- warnings.warn("Undefined frequency: assuming daily!")
- fromfreq = _c.FR_DAY
- else:
- fromfreq = date.freq
-
- if fromfreq == tofreq:
- return date
- else:
- value = cseries.asfreq(numeric.asarray(date.value), fromfreq, tofreq, _rel)
- if value > 0:
- return Date(freq=tofreq, value=value)
- else:
- return None
-Date.asfreq = asfreq
-
def isDate(data):
"Returns whether `data` is an instance of Date."
return isinstance(data, Date) or \
(hasattr(data,'freq') and hasattr(data,'value'))
-
+
#####---------------------------------------------------------------------------
#---- --- DateArray ---
-#####---------------------------------------------------------------------------
+#####---------------------------------------------------------------------------
ufunc_dateOK = ['add','subtract',
'equal','not_equal','less','less_equal', 'greater','greater_equal',
'isnan']
class _datearithmetics(object):
"""Defines a wrapper for arithmetic methods.
-Instead of directly calling a ufunc, the corresponding method of the `array._data`
+Instead of directly calling a ufunc, the corresponding method of the `array._data`
object is called instead.
If `asdates` is True, a DateArray object is returned , else a regular ndarray
is returned.
@@ -590,14 +152,14 @@
if other.dtype.kind not in ['i','f']:
raise ArithmeticDateError
if self._asdates:
- return instance.__class__(method(other, *args),
+ return instance.__class__(method(other, *args),
freq=freq)
else:
return method(other, *args)
-class DateArray(ndarray):
+class DateArray(ndarray):
"""Defines a ndarray of dates, as ordinals.
-
+
When viewed globally (array-wise), DateArray is an array of integers.
When viewed element-wise, DateArray is a sequence of dates.
For example, a test such as :
@@ -605,17 +167,17 @@
will be valid only if value is an integer, not a Date
However, a loop such as :
>>> for d in DateArray(...):
-accesses the array element by element. Therefore, `d` is a Date object.
+accesses the array element by element. Therefore, `d` is a Date object.
"""
- _defcachedinfo = dict(toobj=None, tostr=None, toord=None,
+ _defcachedinfo = dict(toobj=None, tostr=None, toord=None,
steps=None, full=None, hasdups=None)
def __new__(cls, dates=None, freq=None, copy=False):
# Get the frequency ......
if freq is None:
_freq = getattr(dates, 'freq', _c.FR_UND)
else:
- _freq = corelib.check_freq(freq)
- cls._defaultfreq = corelib.check_freq(_freq)
+ _freq = check_freq(freq)
+ cls._defaultfreq = check_freq(_freq)
# Get the dates ..........
_dates = numeric.array(dates, copy=copy, dtype=int_, subok=1)
if _dates.ndim == 0:
@@ -623,29 +185,29 @@
_dates = _dates.view(cls)
_dates.freq = _freq
return _dates
-
+
def __array_wrap__(self, obj, context=None):
if context is None:
return self
elif context[0].__name__ not in ufunc_dateOK:
raise ArithmeticDateError, "(function %s)" % context[0].__name__
-
+
def __array_finalize__(self, obj):
self.freq = getattr(obj, 'freq', _c.FR_UND)
- self._cachedinfo = dict(toobj=None, tostr=None, toord=None,
+ self._cachedinfo = dict(toobj=None, tostr=None, toord=None,
steps=None, full=None, hasdups=None)
if hasattr(obj,'_cachedinfo'):
self._cachedinfo.update(obj._cachedinfo)
return
-
+
def __getitem__(self, indx):
if isinstance(indx, Date):
indx = self.find_dates(indx)
elif numeric.asarray(indx).dtype.kind == 'O':
try:
- indx = self.find_dates(indx)
+ indx = self.find_dates(indx)
except AttributeError:
- pass
+ pass
r = ndarray.__getitem__(self, indx)
if isinstance(r, (generic, int)):
return Date(self.freq, value=r)
@@ -662,7 +224,7 @@
if r._cachedinfo[attr] is not None:
r._cachedinfo[attr] = r._cachedinfo[attr][indx]
return r
-
+
def __repr__(self):
return ndarray.__repr__(self)[:-1] + \
",\n freq='%s')" % self.freqstr
@@ -681,41 +243,41 @@
@property
def freqstr(self):
"Returns the frequency string code."
- return corelib.freq_tostr(self.freq)
+ return check_freq_str(self.freq)
@property
- def day(self):
+ def day(self):
"Returns the day of month."
return self.__getdateinfo__('D')
@property
- def day_of_week(self):
+ def day_of_week(self):
"Returns the day of week."
return self.__getdateinfo__('W')
@property
- def day_of_year(self):
+ def day_of_year(self):
"Returns the day of year."
return self.__getdateinfo__('R')
@property
- def month(self):
+ def month(self):
"Returns the month."
return self.__getdateinfo__('M')
@property
- def quarter(self):
- "Returns the quarter."
+ def quarter(self):
+ "Returns the quarter."
return self.__getdateinfo__('Q')
@property
- def year(self):
+ def year(self):
"Returns the year."
return self.__getdateinfo__('Y')
@property
- def second(self):
- "Returns the seconds."
+ def second(self):
+ "Returns the seconds."
return self.__getdateinfo__('S')
@property
- def minute(self):
- "Returns the minutes."
+ def minute(self):
+ "Returns the minutes."
return self.__getdateinfo__('T')
@property
- def hour(self):
+ def hour(self):
"Returns the hour."
return self.__getdateinfo__('H')
@property
@@ -733,12 +295,12 @@
minutes = minute
hours = hour
weeks = week
-
+
def __getdateinfo__(self, info):
- return numeric.asarray(cseries.getDateInfo(numeric.asarray(self),
- self.freq, info),
+ return numeric.asarray(cseries.DA_getDateInfo(numeric.asarray(self),
+ self.freq, info),
dtype=int_)
- __getDateInfo = __getdateinfo__
+ __getDateInfo = __getdateinfo__
#.... Conversion methods ....................
#
def tovalue(self):
@@ -771,20 +333,20 @@
tostr = firststr
self._cachedinfo['tostr'] = tostr
return self._cachedinfo['tostr']
- #
+ #
def asfreq(self, freq=None, relation="BEFORE"):
"Converts the dates to another frequency."
# Note: As we define a new object, we don't need caching
if freq is None or freq == _c.FR_UND:
return self
- tofreq = corelib.check_freq(freq)
+ tofreq = check_freq(freq)
if tofreq == self.freq:
- return self
- _rel = relation.upper()[0]
+ return self
+ _rel = relation.upper()[0]
fromfreq = self.freq
if fromfreq == _c.FR_UND:
fromfreq = _c.FR_DAY
- new = cseries.asfreq(numeric.asarray(self), fromfreq, tofreq, _rel)
+ new = cseries.DA_asfreq(numeric.asarray(self), fromfreq, tofreq, _rel)
return DateArray(new, freq=freq)
#......................................................
@@ -799,7 +361,7 @@
c = c.nonzero()
if fromnumeric.size(c) == 0:
raise IndexError, "Date out of bounds!"
- return c
+ return c
def date_to_index(self, date):
"Returns the index corresponding to one given date, as an integer."
@@ -811,9 +373,9 @@
else:
index_asarray = (self == date.value).nonzero()
if fromnumeric.size(index_asarray) == 0:
- raise IndexError, "Date out of bounds!"
+ raise IndexError, "Date out of bounds!"
return index_asarray[0][0]
- #......................................................
+ #......................................................
def get_steps(self):
"""Returns the time steps between consecutive dates.
The timesteps have the same unit as the frequency of the series."""
@@ -834,25 +396,25 @@
steps = numeric.array([], dtype=int_)
self._cachedinfo['steps'] = steps
return self._cachedinfo['steps']
-
+
def has_missing_dates(self):
"Returns whether the DateArray have missing dates."
if self._cachedinfo['full'] is None:
steps = self.get_steps()
return not(self._cachedinfo['full'])
-
+
def isfull(self):
"Returns whether the DateArray has no missing dates."
if self._cachedinfo['full'] is None:
steps = self.get_steps()
return self._cachedinfo['full']
-
+
def has_duplicated_dates(self):
"Returns whether the DateArray has duplicated dates."
if self._cachedinfo['hasdups'] is None:
steps = self.get_steps()
return self._cachedinfo['hasdups']
-
+
def isvalid(self):
"Returns whether the DateArray is valid: no missing/duplicated dates."
return (self.isfull() and not self.has_duplicated_dates())
@@ -863,7 +425,7 @@
#####---------------------------------------------------------------------------
#---- --- DateArray functions ---
-#####---------------------------------------------------------------------------
+#####---------------------------------------------------------------------------
def isDateArray(a):
"Tests whether an array is a DateArray object."
return isinstance(a,DateArray)
@@ -915,14 +477,16 @@
float_)
ords += 1
#...try to guess the frequency
- if freq is None:
+ if freq is None or freq == _c.FR_UND:
freq = guess_freq(ords)
#...construct a list of dates
+ for s in dlist:
+ x = Date(freq, string=s)
dates = [Date(freq, string=s) for s in dlist]
# Case #2: dates as numbers .................
elif dlist.dtype.kind in 'if':
#...hopefully, they are values
- if freq is None:
+ if freq is None or freq == _c.FR_UND:
freq = guess_freq(dlist)
dates = dlist
# Case #3: dates as objects .................
@@ -934,7 +498,7 @@
#...as mx.DateTime objects
elif hasattr(template,'absdays'):
# no freq given: try to guess it from absdays
- if freq is None:
+ if freq == _c.FR_UND:
ords = numpy.fromiter((s.absdays for s in dlist), float_)
ords += 1
freq = guess_freq(ords)
@@ -942,7 +506,7 @@
#...as datetime objects
elif hasattr(template, 'toordinal'):
ords = numpy.fromiter((d.toordinal() for d in dlist), float_)
- if freq is None:
+ if freq == _c.FR_UND:
freq = guess_freq(ords)
dates = [Date(freq, datetime=dt.datetime.fromordinal(a)) for a in ords]
#
@@ -950,18 +514,18 @@
return result
-def date_array(dlist=None, start_date=None, end_date=None, length=None,
+def date_array(dlist=None, start_date=None, end_date=None, length=None,
include_last=True, freq=None):
"""Constructs a DateArray from:
- a starting date and either an ending date or a given length.
- a list of dates.
"""
- freq = corelib.check_freq(freq)
+ freq = check_freq(freq)
# Case #1: we have a list ...................
if dlist is not None:
# Already a DateArray....................
if isinstance(dlist, DateArray):
- if (freq is not None) and (dlist.freq != corelib.check_freq(freq)):
+ if (freq != _c.FR_UND) and (dlist.freq != check_freq(freq)):
return dlist.asfreq(freq)
else:
return dlist
@@ -999,7 +563,7 @@
# dlist = [(start_date+i).value for i in range(length)]
dlist = numeric.arange(length, dtype=int_)
dlist += start_date.value
- if freq is None:
+ if freq == _c.FR_UND:
freq = start_date.freq
return DateArray(dlist, freq=freq)
datearray = date_array
@@ -1008,12 +572,12 @@
"Constructs a DateArray from a list of dates."
return date_array(dlist=dlist, freq=freq)
-def date_array_fromrange(start_date, end_date=None, length=None,
+def date_array_fromrange(start_date, end_date=None, length=None,
include_last=True, freq=None):
- """Constructs a DateArray from a starting date and either an ending date or
+ """Constructs a DateArray from a starting date and either an ending date or
a length."""
- return date_array(start_date=start_date, end_date=end_date,
- length=length, include_last=include_last, freq=freq)
+ return date_array(start_date=start_date, end_date=end_date,
+ length=length, include_last=include_last, freq=freq)
#####---------------------------------------------------------------------------
#---- --- Definition of functions from the corresponding methods ---
@@ -1089,7 +653,7 @@
hodie = today('D')
D = DateArray(today('D'))
assert_equal(D.freq, 6000)
-
+
if 0:
freqs = [x[0] for x in corelib.freq_dict.values() if x[0] != 'U']
print freqs
@@ -1097,17 +661,17 @@
print f
today = thisday(f)
assert(Date(freq=f, value=today.value) == today)
-
+
if 1:
D = date_array(freq='U', start_date=Date('U',1), length=10)
-
+
if 1:
dlist = ['2007-01-%02i' % i for i in (1,2,4,5,7,8,10,11,13)]
-
-
+
+
ords = numpy.fromiter((DateTimeFromString(s).toordinal() for s in dlist),
float_)
-
+
if 1:
"Tests the automatic sorting of dates."
D = date_array_fromlist(dlist=['2006-01','2005-01','2004-01'],freq='M')
Modified: trunk/Lib/sandbox/timeseries/tests/test_dates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_dates.py 2007-03-20 14:42:18 UTC (rev 2851)
+++ trunk/Lib/sandbox/timeseries/tests/test_dates.py 2007-03-20 14:44:08 UTC (rev 2852)
@@ -1,5 +1,5 @@
# pylint: disable-msg=W0611, W0612, W0511,R0201
-"""Tests suite for timeseries.tdates.
+"""Tests suite for Date handling.
:author: Pierre Gerard-Marchant & Matt Knox
:contact: pierregm_at_uga_dot_edu - mattknow_ca_at_hotmail_dot_com
@@ -25,20 +25,20 @@
import maskedarray.testutils
from maskedarray.testutils import assert_equal, assert_array_equal
-import timeseries.tdates as tdates
-from timeseries.tdates import *
-from timeseries.parser import DateFromString
-from timeseries import tcore
+import timeseries as ts
+from timeseries import *
+from timeseries.cseries import freq_dict
class test_creation(NumpyTestCase):
"Base test class for MaskedArrays."
-
+
def __init__(self, *args, **kwds):
NumpyTestCase.__init__(self, *args, **kwds)
-
+
def test_fromstrings(self):
"Tests creation from list of strings"
+ print "starting test_fromstrings..."
dlist = ['2007-01-%02i' % i for i in range(1,15)]
# A simple case: daily data
dates = date_array_fromlist(dlist, 'D')
@@ -72,9 +72,11 @@
assert(dates.isfull())
assert(not dates.has_duplicated_dates())
assert_equal(dates, 24073 + numpy.arange(12))
-
+ print "finished test_fromstrings"
+
def test_fromstrings_wmissing(self):
"Tests creation from list of strings w/ missing dates"
+ print "starting test_fromstrings_wmissing..."
dlist = ['2007-01-%02i' % i for i in (1,2,4,5,7,8,10,11,13)]
dates = date_array_fromlist(dlist)
assert_equal(dates.freqstr,'U')
@@ -91,10 +93,12 @@
assert_equal(mdates.freqstr,'M')
assert(not dates.isfull())
assert(mdates.has_duplicated_dates())
+ print "finished test_fromstrings_wmissing"
#
-
+
def test_fromsobjects(self):
"Tests creation from list of objects."
+ print "starting test_fromsobjects..."
dlist = ['2007-01-%02i' % i for i in (1,2,4,5,7,8,10,11,13)]
dates = date_array_fromlist(dlist)
dobj = [datetime.datetime.fromordinal(d) for d in dates.toordinal()]
@@ -103,17 +107,21 @@
dobj = [DateFromString(d) for d in dlist]
odates = date_array_fromlist(dobj)
assert_equal(dates,odates)
+ print "finished test_fromsobjects"
def test_consistent_value(self):
"Tests that values don't get mutated when constructing dates from a value"
- freqs = [x[0] for x in tcore.freq_dict.values() if x[0] != 'U']
+ print "starting test_consistent_value..."
+ freqs = [x[0] for x in freq_dict.values() if x[0] != 'U']
print freqs
for f in freqs:
- today = tdates.thisday(f)
- assert_equal(tdates.Date(freq=f, value=today.value), today)
-
+ today = thisday(f)
+ assert_equal(Date(freq=f, value=today.value), today)
+ print "finished test_consistent_value"
+
def test_shortcuts(self):
"Tests some creation shortcuts. Because I'm lazy like that."
+ print "starting test_shortcuts..."
# Dates shortcuts
assert_equal(Date('D','2007-01'), Date('D',string='2007-01'))
assert_equal(Date('D','2007-01'), Date('D', value=732677))
@@ -123,26 +131,27 @@
d = date_array(start_date=n, length=3)
assert_equal(date_array(n,length=3), d)
assert_equal(date_array(n, n+2), d)
+ print "finished test_shortcuts"
class test_date_properties(NumpyTestCase):
"Test properties such as year, month, day_of_week, etc...."
-
+
def __init__(self, *args, **kwds):
NumpyTestCase.__init__(self, *args, **kwds)
def test_properties(self):
-
- a_date = tdates.Date(freq='A', year=2007)
- q_date = tdates.Date(freq='Q', year=2007, quarter=1)
- m_date = tdates.Date(freq='M', year=2007, month=1)
- w_date = tdates.Date(freq='W', year=2007, month=1, day=7)
- b_date = tdates.Date(freq='B', year=2007, month=1, day=1)
- d_date = tdates.Date(freq='D', year=2007, month=1, day=1)
- h_date = tdates.Date(freq='H', year=2007, month=1, day=1,
+
+ a_date = Date(freq='A', year=2007)
+ q_date = Date(freq='Q', year=2007, quarter=1)
+ m_date = Date(freq='M', year=2007, month=1)
+ w_date = Date(freq='W', year=2007, month=1, day=7)
+ b_date = Date(freq='B', year=2007, month=1, day=1)
+ d_date = Date(freq='D', year=2007, month=1, day=1)
+ h_date = Date(freq='H', year=2007, month=1, day=1,
hour=0)
- t_date = tdates.Date(freq='T', year=2007, month=1, day=1,
+ t_date = Date(freq='T', year=2007, month=1, day=1,
hour=0, minute=0)
- s_date = tdates.Date(freq='T', year=2007, month=1, day=1,
+ s_date = Date(freq='T', year=2007, month=1, day=1,
hour=0, minute=0, second=0)
assert_equal(a_date.year, 2007)
@@ -219,12 +228,12 @@
class test_freq_conversion(NumpyTestCase):
"Test frequency conversion of date objects"
-
+
def __init__(self, *args, **kwds):
NumpyTestCase.__init__(self, *args, **kwds)
self.dateWrap = [(dArrayWrap, assert_array_equal),
(noWrap, assert_equal)]
-
+
def test_conv_annual(self):
"frequency conversion tests: from Annual Frequency"
@@ -240,17 +249,17 @@
date_A_to_B_after = dWrap(Date(freq='B', year=2007, month=12, day=31))
date_A_to_D_before = dWrap(Date(freq='D', year=2007, month=1, day=1))
date_A_to_D_after = dWrap(Date(freq='D', year=2007, month=12, day=31))
- date_A_to_H_before = dWrap(Date(freq='H', year=2007, month=1, day=1,
+ date_A_to_H_before = dWrap(Date(freq='H', year=2007, month=1, day=1,
hour=0))
- date_A_to_H_after = dWrap(Date(freq='H', year=2007, month=12, day=31,
+ date_A_to_H_after = dWrap(Date(freq='H', year=2007, month=12, day=31,
hour=23))
- date_A_to_T_before = dWrap(Date(freq='T', year=2007, month=1, day=1,
+ date_A_to_T_before = dWrap(Date(freq='T', year=2007, month=1, day=1,
hour=0, minute=0))
- date_A_to_T_after = dWrap(Date(freq='T', year=2007, month=12, day=31,
+ date_A_to_T_after = dWrap(Date(freq='T', year=2007, month=12, day=31,
hour=23, minute=59))
- date_A_to_S_before = dWrap(Date(freq='S', year=2007, month=1, day=1,
+ date_A_to_S_before = dWrap(Date(freq='S', year=2007, month=1, day=1,
hour=0, minute=0, second=0))
- date_A_to_S_after = dWrap(Date(freq='S', year=2007, month=12, day=31,
+ date_A_to_S_after = dWrap(Date(freq='S', year=2007, month=12, day=31,
hour=23, minute=59, second=59))
assert_func(date_A.asfreq('Q', "BEFORE"), date_A_to_Q_before)
@@ -270,7 +279,7 @@
assert_func(date_A.asfreq('S', "BEFORE"), date_A_to_S_before)
assert_func(date_A.asfreq('S', "AFTER"), date_A_to_S_after)
-
+
def test_conv_quarterly(self):
"frequency conversion tests: from Quarterly Frequency"
@@ -286,17 +295,17 @@
date_Q_to_B_after = dWrap(Date(freq='B', year=2007, month=3, day=30))
date_Q_to_D_before = dWrap(Date(freq='D', year=2007, month=1, day=1))
date_Q_to_D_after = dWrap(Date(freq='D', year=2007, month=3, day=31))
- date_Q_to_H_before = dWrap(Date(freq='H', year=2007, month=1, day=1,
+ date_Q_to_H_before = dWrap(Date(freq='H', year=2007, month=1, day=1,
hour=0))
- date_Q_to_H_after = dWrap(Date(freq='H', year=2007, month=3, day=31,
+ date_Q_to_H_after = dWrap(Date(freq='H', year=2007, month=3, day=31,
hour=23))
- date_Q_to_T_before = dWrap(Date(freq='T', year=2007, month=1, day=1,
+ date_Q_to_T_before = dWrap(Date(freq='T', year=2007, month=1, day=1,
hour=0, minute=0))
- date_Q_to_T_after = dWrap(Date(freq='T', year=2007, month=3, day=31,
+ date_Q_to_T_after = dWrap(Date(freq='T', year=2007, month=3, day=31,
hour=23, minute=59))
- date_Q_to_S_before = dWrap(Date(freq='S', year=2007, month=1, da