File:  [parser3project] / parser3 / src / classes / date.C
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Sat Jul 7 17:59:02 2001 UTC (25 years ago) by parser
Branches: MAIN
CVS tags: HEAD
date roll
table calendar

/** @file
	Parser: @b date parser class.

	Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)

	Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)

	$Id: date.C,v 1.2 2001/07/07 17:59:02 parser Exp $
*/
static const char *RCSId="$Id: date.C,v 1.2 2001/07/07 17:59:02 parser Exp $"; 

#include "classes.h"
#include "pa_request.h"
#include "pa_vdouble.h"
#include "pa_vdate.h"

// defines

#define DATE_CLASS_NAME "date"

// class

class MDate : public Methoded {
public: // VStateless_class
	Value *create_new_value(Pool& pool) { return new(pool) VDate(pool, 0); }

public:
	MDate(Pool& pool);
public: // Methoded
	bool used_directly() { return true; }
};

// methods

static void _now(Request& r, const String& method_name, MethodParams *) {
	Pool& pool=r.pool();
	VDate *vdate=static_cast<VDate *>(r.self);
	vdate->set_time(time(0));
}

static void _set(Request& r, const String& method_name, MethodParams *params) {
	Pool& pool=r.pool();
	VDate *vdate=static_cast<VDate *>(r.self);

	time_t time;
	if(params->size()==1) // ^set(float days)
		time=(time_t)(params->as_double(0, r)*SECS_PER_DAY);
	else if(params->size()>=3) { // ^set(y;m;d[;h[;m[;s]]])
		tm tmIn={0};
		tmIn.tm_isdst=-1;
		int year=params->as_int(0, r);
		if(year<70) // 0..69 -> 100..169 [2000..2069]
			year+=100;
		tmIn.tm_year=year;
		tmIn.tm_mon=params->as_int(1, r)-1;
		tmIn.tm_mday=params->as_int(2, r);
		if(params->size()>3) tmIn.tm_hour=params->as_int(3, r);
		if(params->size()>4) tmIn.tm_min=params->as_int(4, r);
		if(params->size()>5) tmIn.tm_sec=params->as_int(5, r);
		time=mktime(&tmIn);
		if(time<0)
			PTHROW(0, 0,
				&method_name,
				"invalid datetime");
	} else
		PTHROW(0, 0,
			&method_name,
			"invalid params count, must be 1 or >=3");
	vdate->set_time(time);
}

static void _string(Request& r, const String& method_name, MethodParams *) {
	Pool& pool=r.pool();
	VDate *vdate=static_cast<VDate *>(r.self);
	int size=1+ 4+1+2+1+2 +1+ 2+1+2+1+2 +1 +1;
	char *buf=(char *)pool.malloc(size);
	time_t time=vdate->get_time();
	size=strftime(buf, size, "'%Y-%m-%d %H:%M:%S'", gmtime(&time));
	
	Value& result=*new(pool) VString(*new(pool) String(pool, buf, size));
	r.write_assign_lang(result);
}


static void _roll(Request& r, const String& method_name, MethodParams *params) {
	Pool& pool=r.pool();
	VDate *vdate=static_cast<VDate *>(r.self);

	const String& what=params->as_string(0, "'what' must be string");
    int oyear=0;
    int omonth=0;
    int oday=0;
	int *offset;
	if(what=="year") offset=&oyear;
	else if(what=="month") offset=&omonth;
	else if(what=="day") offset=&oday;
	else
		PTHROW(0, 0,
			&what,
			"must be year|month|day");
	
	*offset=params->as_int(1, r);
	if(!(*offset==1 || *offset==-1))
		PTHROW(0, 0,
			&method_name,
			"offset must be +/- 1");

	time_t tIn=vdate->get_time();
    tm *tmIn=localtime(&tIn);
	tmIn->tm_year+=oyear;
	time_t t=mktime(tmIn);
	if(t<0)
		PTHROW(0, 0,
			&method_name,
			"invalid datetime");
	t+=omonth*getMonthDays(tmIn->tm_year, (tmIn->tm_mon+(omonth<0?-1:0)+12)%12)*SECS_PER_DAY;
    t+=oday*SECS_PER_DAY;
	vdate->set_time(t);
}

// constructor

MDate::MDate(Pool& apool) : Methoded(apool) {
	set_name(*NEW String(pool(), DATE_CLASS_NAME));


	// ^now[]
	add_native_method("now", Method::CT_DYNAMIC, _now, 0, 0);

	// ^set(float days)
	add_native_method("set", Method::CT_DYNAMIC, _set, 1, 6);

	// ^string[]
	add_native_method("string", Method::CT_DYNAMIC, _string, 0, 0);

	// ^roll(year|month|day;+/- 1)
	add_native_method("roll", Method::CT_DYNAMIC, _roll, 2, 2);

}
// global variable

Methoded *date_class;

// creator

Methoded *MDate_create(Pool& pool) {
	return date_class=new(pool) MDate(pool);
}

E-mail: