Annotation of parser3/src/types/pa_vdate.h, revision 1.38.6.3
1.1 parser 1: /** @file
2: Parser: @b date parser class decl.
3:
1.38.6.1 paf 4: Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)
1.8 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1 parser 6: */
7:
8: #ifndef PA_VDATE_H
9: #define PA_VDATE_H
1.11 paf 10:
1.38.6.3! paf 11: static const char * const IDENT_VDATE_H="$Date: 2005/08/26 12:35:55 $";
1.1 parser 12:
13: #include "classes.h"
14: #include "pa_common.h"
15: #include "pa_vstateless_object.h"
16: #include "pa_vint.h"
17:
1.9 paf 18: // defines
19:
20: #define VDATE_TYPE "date"
1.20 paf 21:
1.9 paf 22: // externs
23:
1.25 paf 24: extern Methoded* date_class;
1.1 parser 25:
1.27 paf 26: inline void set_tz(const char* tz, char* buf, size_t buf_size) {
1.38 paf 27: if(tz){
28: snprintf(buf, buf_size, "TZ=%s", tz);
29: putenv(buf);
30: } else
31: putenv("TZ");
1.27 paf 32: tzset();
33: }
34:
1.1 parser 35: /// value of type 'date'. implemented with @c time_t
1.25 paf 36: class VDate: public VStateless_object {
1.1 parser 37: public: // Value
38:
1.25 paf 39: override const char* type() const { return VDATE_TYPE; }
40: override VStateless_class *get_class() { return date_class; }
1.10 paf 41:
1.1 parser 42: /// VDate: ftime -> float days
1.28 paf 43: override Value& as_expr_result(bool /*return_string_as_is=false*/) { return *new VDouble(as_double()); }
1.1 parser 44:
45: /// VDate: ftime -> float days
1.25 paf 46: override double as_double() const { return ((double)ftime)/ SECS_PER_DAY; }
1.1 parser 47: /// VDate: 0 or !0
1.25 paf 48: override bool as_bool() const { return ftime!=0; }
1.1 parser 49:
1.38.6.3! paf 50: /// @TODO 'static' approach is NOT thread safe!
1.38.6.2 paf 51: tm& get_localtime()
1.35 paf 52: {
1.38.6.3! paf 53: char saved_tz[MAX_STRING];
! 54: static char saved_tz_pair[MAX_STRING]; //TODO: this is NOT thread safe!
1.35 paf 55: static char temp_tz_pair[MAX_STRING];
56: if(ftz_cstr) {
1.38.6.3! paf 57: if(const char* ltz=getenv("TZ")) {
! 58: strncpy(saved_tz, ltz, sizeof(saved_tz)-1);
! 59: saved_tz[sizeof(saved_tz)-1]=0;
! 60: } else
! 61: saved_tz[0]=0;
! 62:
1.35 paf 63: ::set_tz(ftz_cstr, temp_tz_pair, sizeof(temp_tz_pair));
64: }
65: tm *result=::localtime(&ftime);
1.38 paf 66: if(ftz_cstr) {
1.35 paf 67: ::set_tz(saved_tz, saved_tz_pair, sizeof(saved_tz_pair));
1.38 paf 68: }
1.35 paf 69: if(!result)
70: throw Exception(0,
71: 0,
72: "invalid datetime (after changing TZ)");
73:
1.38.6.2 paf 74: return *result;
1.35 paf 75: }
76:
1.1 parser 77:
1.15 paf 78: /// VDate: method,field
1.25 paf 79: override Value* get_element(const String& aname, Value& aself, bool looking_up) {
1.15 paf 80: // $method
1.25 paf 81: if(Value* result=VStateless_object::get_element(aname, aself, looking_up))
1.1 parser 82: return result;
83:
1.27 paf 84: // $TZ
85: if(aname=="TZ")
1.37 paf 86: return ftz? new VString(*ftz): new VString();
1.27 paf 87:
1.1 parser 88: // $year month day hour minute second weekday
1.38.6.2 paf 89: tm& tms=get_localtime();
1.27 paf 90:
1.1 parser 91: int result;
1.38.6.2 paf 92: if(aname=="year") result=1900+tms.tm_year;
93: else if(aname=="month") result=1+tms.tm_mon;
94: else if(aname=="day") result=tms.tm_mday;
95: else if(aname=="hour") result=tms.tm_hour;
96: else if(aname=="minute") result=tms.tm_min;
97: else if(aname=="second") result=tms.tm_sec;
98: else if(aname=="weekday") result=tms.tm_wday;
99: else if(aname=="yearday") result=tms.tm_yday;
100: else if(aname=="daylightsaving") result=tms.tm_isdst;
101: else if(aname=="week") result=week_no(tms);
1.26 paf 102: else { return bark("%s field not found", &aname); }
1.25 paf 103: return new VInt(result);
1.1 parser 104: }
105:
106: public: // usage
107:
1.27 paf 108: VDate(time_t adate) :
109: ftz(0),
110: ftz_cstr(0) {
1.33 paf 111: set_time(adate);
1.27 paf 112: }
1.1 parser 113:
1.32 paf 114: VDate(tm tmIn) :
115: ftime(0),
116: ftz(0),
117: ftz_cstr(0) {
118: set_time(tmIn);
119: }
120:
1.19 paf 121: time_t get_time() const { return ftime; }
1.32 paf 122: void set_time(time_t atime) {
123: if(atime<0)
124: throw Exception(0,
125: 0,
126: "invalid datetime");
127: ftime=atime;
128: }
129: void set_time(tm tmIn) {
130: time_t t=mktime(&tmIn);
131: if(t<0) {
132: // on some platforms mktime does not fix spring daylightsaving time hole
133: // in russia -- last sunday of march, 2am->3am hole
134: // trying to recover:
135: tmIn.tm_hour--;
136: t=mktime(&tmIn);
137: }
138: set_time(t);
139: }
1.27 paf 140: void set_tz(const String* atz) {
1.30 paf 141: if((ftz=atz))
1.27 paf 142: ftz_cstr=ftz->cstr();
1.38.6.2 paf 143: }
144:
145: static int week_no(tm& tms) {
146: // http://www.merlyn.demon.co.uk/weekinfo.htm
147: int weekyear=tms.tm_year+1900;
148: const int FirstThurs[] = {7,5,4,3,2,7,6,5,4,2,1,7,6,4,3,2,1,6,5,4,3,1,7,6,5,3,2,1};
149: return 1 + (tms.tm_yday-(FirstThurs[weekyear % 28]-3))/7;
1.27 paf 150: }
1.1 parser 151:
152: private:
153:
154: time_t ftime;
1.27 paf 155: const String* ftz;
156: const char* ftz_cstr;
1.1 parser 157:
158: };
159:
160: #endif
E-mail: