/** Convert from a timestamp to a string -- deltamode **/ int convert_from_delta_timestamp(double ts_v, char *buffer, int size) { TIMESTAMP ts; unsigned int nano_seconds; char temp[64]="INVALID"; int len=(int)strlen(temp); /* Convert to integer */ ts = (int64)ts_v; /* Figure out the nanosecond portion - bias slightly*/ nano_seconds = (unsigned int)((ts_v - (double)(ts))*1e9 + 0.5); if (ts>=365*DAY) { DATETIME t; if (ts>=0) { if (ts<TS_NEVER) { if (local_datetime(ts,&t)) { t.nanosecond = nano_seconds; len = strdatetime(&t,temp,sizeof(temp)); } else THROW("%"FMT_INT64"d is an invalid timestamp", ts); /* TROUBLESHOOT An attempt to convert a timestamp to a date/time string has failed because the timezone isn't valid. This is most likely an internal error and should be reported. */ } else len=sprintf(temp,"%s","NEVER"); } } else if (ts>=DAY) len=sprintf(temp,"%lfd",(double)ts/DAY); else if (ts>=HOUR) len=sprintf(temp,"%lfh",(double)ts/HOUR); else if (ts>=MINUTE) len=sprintf(temp,"%lfm",(double)ts/MINUTE); else if (ts>=SECOND) len=sprintf(temp,"%lfs",(double)ts/SECOND); else if (ts==0) len=sprintf(temp,"%s","INIT"); else len=sprintf(temp,"%"FMT_INT64"d",ts); if (len<size) { if(ts == TS_NEVER){ strcpy(buffer, "NEVER"); return (int)strlen("NEVER"); } strcpy(buffer,temp); return len; } else return 0; }
void CGldEditorView::LoadScheduleBlock(SCHEDULE *sch, unsigned int block) { CListCtrl &list = GetListCtrl(); int nColumns = list.GetHeaderCtrl()?list.GetHeaderCtrl()->GetItemCount():0; for (int i=0; i<nColumns; i++) list.DeleteColumn(0); CRect wr; list.GetClientRect(&wr); int nCol=0; int nWid=0; #define W(X) (nWid+=X,X) int Cal = list.InsertColumn(nCol++,"Month",LVCFMT_LEFT,W(150),nCol); int dowCol[8]; dowCol[0] = list.InsertColumn(nCol++,"Sun",LVCFMT_LEFT,W(50),nCol); dowCol[1] = list.InsertColumn(nCol++,"Mon",LVCFMT_LEFT,W(50),nCol); dowCol[2] = list.InsertColumn(nCol++,"Tue",LVCFMT_LEFT,W(50),nCol); dowCol[3] = list.InsertColumn(nCol++,"Wed",LVCFMT_LEFT,W(50),nCol); dowCol[4] = list.InsertColumn(nCol++,"Thu",LVCFMT_LEFT,W(50),nCol); dowCol[5] = list.InsertColumn(nCol++,"Fri",LVCFMT_LEFT,W(50),nCol); dowCol[6] = list.InsertColumn(nCol++,"Sat",LVCFMT_LEFT,W(50),nCol); dowCol[7] = list.InsertColumn(nCol++,"Hol",LVCFMT_LEFT,W(50),nCol); #undef W char *months[] = {"January","February","March","April","May","June","July","August","September","October","November","December"}; int days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int year=2000; for (int month=1; month<=12; month++) { char buffer[64]; sprintf(buffer,"%s",months[month-1]); int nItem = list.InsertItem(list.GetItemCount(),buffer); int hItem[24]; for (int hour=0; hour<24; hour++) { char buffer[64]; sprintf(buffer," %d:00",hour); hItem[hour] = list.InsertItem(list.GetItemCount(),buffer); } for (int day=0; day<7; day++) { for (int hour=0; hour<24; hour++) { DATETIME dt = {year,month,day+1,hour,0,0}; TIMESTAMP ts = mkdatetime(&dt); local_datetime(ts,&dt); SCHEDULEINDEX ref = schedule_index(sch,ts); double value = schedule_value(sch,ref); char buffer[64]; sprintf(buffer,"%g%c",value,schedule_dtnext(sch,ref)<60?'*':' '); list.SetItemText(hItem[hour],dowCol[dt.weekday],buffer); } } } }
double timestamp_get_part(void *x, char *name) { TIMESTAMP ts = *(TIMESTAMP*)x; DATETIME dt; if ( strcmp(name,"seconds")==0 ) return (double)ts; if ( strcmp(name,"minutes")==0 ) return (double)ts/60; if ( strcmp(name,"hours")==0 ) return (double)ts/3600; if ( strcmp(name,"days")==0 ) return (double)ts/86400; if ( local_datetime(ts,&dt) ) { if ( strcmp(name,"second")==0 ) return (double)dt.second; if ( strcmp(name,"minute")==0 ) return (double)dt.minute; if ( strcmp(name,"hour")==0 ) return (double)dt.hour; if ( strcmp(name,"day")==0 ) return (double)dt.day; if ( strcmp(name,"month")==0 ) return (double)dt.month; if ( strcmp(name,"year")==0 ) return (double)dt.year; if ( strcmp(name,"weekday")==0 ) return (double)dt.weekday; if ( strcmp(name,"yearday")==0 ) return (double)dt.yearday; if ( strcmp(name,"isdst")==0 ) return (double)dt.is_dst; } return QNAN; }
void CGldEditorView::LoadSchedule(SCHEDULE *sch) { CListCtrl &list = GetListCtrl(); int nColumns = list.GetHeaderCtrl()?list.GetHeaderCtrl()->GetItemCount():0; for (int i=0; i<nColumns; i++) list.DeleteColumn(0); CRect wr; list.GetClientRect(&wr); int nCol=0; int nWid=0; #define W(X) (nWid+=X,X) int year = list.InsertColumn(nCol++,"Year",LVCFMT_LEFT,W(45),nCol); int month = list.InsertColumn(nCol++,"Month",LVCFMT_LEFT,W(50),nCol); int weekday = list.InsertColumn(nCol++,"Weekday",LVCFMT_LEFT,W(60),nCol); int day = list.InsertColumn(nCol++,"Day",LVCFMT_RIGHT,W(35),nCol); int hour = list.InsertColumn(nCol++,"Time",LVCFMT_RIGHT,W(50),nCol); int value = list.InsertColumn(nCol++,"Value",LVCFMT_RIGHT,W(50),nCol); #undef W TIMESTAMP tstart = global_clock; // TODO: this should be global_starttime but it's already been set to wall clock by this time TIMESTAMP tstop = global_stoptime; if (tstart==0) { time_t now = time(NULL); struct tm* ts = localtime(&now); DATETIME dt = {ts->tm_year,1,1,0,0,0,0,0}; tstart = mkdatetime(&dt); } if (tstop==TS_NEVER || tstop<tstart) { DATETIME dt; local_datetime(tstart,&dt); dt.year++; tstop = mkdatetime(&dt); } TIMESTAMP t = tstart; DATETIME last = {0,0,0,-1,0,0}; // -1 forces first time to be displayed even when it's midnight int max = 100; double lastvalue=-1; // -1 forces first time to be displayed even when it's zero value while (t<tstop )// && max-->0) { SCHEDULEINDEX ndx = schedule_index(sch,t); DATETIME next; local_datetime(t,&next); double nextvalue = schedule_value(sch,ndx); if (nextvalue!=lastvalue) { int hItem = list.InsertItem(list.GetItemCount(),""); CString buf; if (last.year!=next.year) { buf.Format("%d",next.year); list.SetItemText(hItem,year,buf); last.year = next.year; } if (last.month!=next.month) { char *mon[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; list.SetItemText(hItem,month,mon[next.month-1]); last.month = next.month; } if (last.day!=next.day) { buf.Format("%d",next.day); list.SetItemText(hItem,day,buf); last.day = next.day; char *wd[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; list.SetItemText(hItem,weekday,wd[next.weekday]); } if (last.hour!=next.hour || last.minute!=next.minute) { buf.Format("%d:%02d",next.hour,next.minute); list.SetItemText(hItem,hour,buf); last.hour = next.hour; last.minute = next.minute; } buf.Format("%g", nextvalue); list.SetItemText(hItem,value,buf); lastvalue = nextvalue; } t+=schedule_dtnext(sch,ndx)*60; // TODO increment by dtnext } }
/** Test the daylight saving time calculations @return the number of test the failed **/ int timestamp_test(void) { #define NYEARS 50 int year; static DATETIME last_t; TIMESTAMP step = SECOND; TIMESTAMP ts; char buf1[64], buf2[64]; char steptxt[32]; TIMESTAMP *event[]={dststart,dstend}; int failed=0, succeeded=0; output_test("BEGIN: daylight saving time event test for TZ=%s...", current_tzname); convert_from_timestamp(step,steptxt,sizeof(steptxt)); for (year=0; year<NYEARS; year++) { int test; for (test=0; test<2; test++) { for (ts=(event[test])[year]-2*step; ts<(event[test])[year]+2*step;ts+=step) { DATETIME t; if (local_datetime(ts,&t)) { if (last_t.is_dst!=t.is_dst) output_test("%s + %s = %s", strdatetime(&last_t,buf1,sizeof(buf1))?buf1:"(invalid)", steptxt, strdatetime(&t,buf2,sizeof(buf2))?buf2:"(invalid)"); last_t = t; succeeded++; } else { output_test("FAILED: unable to convert ts=%"FMT_INT64"d to local time", ts); failed++; } } } } output_test("END: daylight saving time event test"); step=HOUR; convert_from_timestamp(step,steptxt,sizeof(steptxt)); output_test("BEGIN: round robin test at %s timesteps",steptxt); for (ts=DAY+tzoffset; ts<DAY*365*NYEARS; ts+=step) { DATETIME t; if (local_datetime(ts,&t)) { TIMESTAMP tt = mkdatetime(&t); convert_from_timestamp(ts,buf1,sizeof(buf1)); convert_from_timestamp(tt,buf2,sizeof(buf2)); if (tt==TS_INVALID) { output_test("FAILED: unable to extract %04d-%02d-%02d %02d:%02d:%02d %s (dow=%s, doy=%d)", t.year,t.month,t.day,t.hour,t.minute,t.second,t.tz,dow[t.weekday],t.yearday); failed++; } else if (tt!=ts) { output_test("FAILED: unable to match %04d-%02d-%02d %02d:%02d:%02d %s (dow=%s, doy=%d)\n from=%s, to=%s", t.year,t.month,t.day,t.hour,t.minute,t.second,t.tz,dow[t.weekday],t.yearday,buf1,buf2); failed++; } else if (convert_to_timestamp(buf1)!=ts) { output_test("FAILED: unable to convert %04d-%02d-%02d %02d:%02d:%02d %s (dow=%s, doy=%d) back to a timestamp\n from=%s, to=%s", t.year,t.month,t.day,t.hour,t.minute,t.second,t.tz,dow[t.weekday],t.yearday,buf1,buf2); output_test(" expected %" FMT_INT64 "d but got %" FMT_INT64 "d", ts, convert_to_timestamp(buf1)); failed++; } else succeeded++; } else { output_test("FAILED: timestamp_test: unable to convert ts=%"FMT_INT64"d to local time", ts); failed++; } } output_test("END: round robin test",steptxt); output_test("END: daylight saving time tests for %d to %d", YEAR0, YEAR0+NYEARS); output_verbose("daylight saving time tests: %d succeeded, %d failed (see '%s' for details)", succeeded, failed, global_testoutputfile); return failed; }