diff --git a/runtime/datetime.c b/runtime/datetime.c index ba2ed35aa..ddcc732ac 100644 --- a/runtime/datetime.c +++ b/runtime/datetime.c @@ -1080,7 +1080,42 @@ int getWeekdayNbr(struct syslogTime *ts) return wday; } +/* getOrdinal - 1-366 day of the year + * I've given little thought to leap seconds here. + */ +int getOrdinal(struct syslogTime *ts) +{ + int yday; + struct syslogTime yt; + time_t thistime; + time_t previousyears; + time_t seconds_into_year; + thistime = syslogTime2time_t(ts); + + /* initialize a timestamp from the previous years */ + yt.year = ts->year - 1; + yt.month = 12; + yt.day = 31; + yt.hour = 23; + yt.minute = 59; + yt.second = 59; + yt.secfracPrecision = 0; + yt.secfrac = 0; + yt.OffsetMinute = ts->OffsetMinute; + yt.OffsetHour = ts->OffsetHour; + yt.OffsetMode = ts->OffsetMode; + yt.timeType = TIME_TYPE_RFC3164; /* low-res time */ + + previousyears = syslogTime2time_t(&yt); + + /* subtract seconds from previous years */ + seconds_into_year = thistime - previousyears; + + /* divide by seconds in a day and truncate to int */ + yday = seconds_into_year / 86400; + return yday; +} /* queryInterface function * rgerhards, 2008-03-05 diff --git a/runtime/datetime.h b/runtime/datetime.h index c96f7eef0..64d26ee20 100644 --- a/runtime/datetime.h +++ b/runtime/datetime.h @@ -68,5 +68,6 @@ ENDinterface(datetime) PROTOTYPEObj(datetime); void applyDfltTZ(struct syslogTime *pTime, char *tz); int getWeekdayNbr(struct syslogTime *ts); +int getOrdinal(struct syslogTime *ts); #endif /* #ifndef INCLUDED_DATETIME_H */ diff --git a/runtime/msg.c b/runtime/msg.c index 66c3b7b5f..8f808329a 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -98,6 +98,46 @@ static char *two_digits[100] = { static char *wdayNames[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +/* Table of days in a year, needed for getYearDay */ +static char *daysInYear[366] = { + "001", "002", "003", "004", "005", "006", "007", "008", "009", + "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", + "020", "021", "022", "023", "024", "025", "026", "027", "028", "029", + "030", "031", "032", "033", "034", "035", "036", "037", "038", "039", + "040", "041", "042", "043", "044", "045", "046", "047", "048", "049", + "050", "051", "052", "053", "054", "055", "056", "057", "058", "059", + "060", "061", "062", "063", "064", "065", "066", "067", "068", "069", + "070", "071", "072", "073", "074", "075", "076", "077", "078", "079", + "080", "081", "082", "083", "084", "085", "086", "087", "088", "089", + "090", "091", "092", "093", "094", "095", "096", "097", "098", "099", + "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", + "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", + "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", + "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", + "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", + "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", + "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", + "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", + "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", + "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", + "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", + "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", + "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", + "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", + "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", + "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", + "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", + "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", + "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", + "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", + "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", + "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", + "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", + "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", + "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", + "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", + "360", "361", "362", "363", "364", "365", "366"}; + /* The following is a table of supported years. This permits us * to avoid dynamic memory allocation. Note that the time-based * algos need to be upgraded after the year 2099 in any case. @@ -1657,6 +1697,8 @@ getTimeReported(msg_t * const pM, enum tplFormatTypes eFmt) return two_digits[(int)pM->tTIMESTAMP.OffsetMinute]; case tplFmtTZOffsDirection: return (pM->tTIMESTAMP.OffsetMode == '+')? "+" : "-"; + case tplFmtOrdinal: + return daysInYear[getOrdinal(&pM->tTIMESTAMP)]; } ENDfunc return "INVALID eFmt OPTION!"; @@ -1768,6 +1810,8 @@ static char *getTimeGenerated(msg_t * const pM, enum tplFormatTypes eFmt) return two_digits[(int)pM->tRcvdAt.OffsetMinute]; case tplFmtTZOffsDirection: return (pM->tRcvdAt.OffsetMode == '+')? "+" : "-"; + case tplFmtOrdinal: + return daysInYear[getOrdinal(&pM->tRcvdAt)]; } ENDfunc return "INVALID eFmt OPTION!"; diff --git a/template.c b/template.c index 29c46a275..74ede25db 100644 --- a/template.c +++ b/template.c @@ -726,6 +726,8 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe) pTpe->data.field.eDateFormat = tplFmtTZOffsMin; } else if(!strcmp((char*)Buf, "date-tzoffsdirection")) { pTpe->data.field.eDateFormat = tplFmtTZOffsDirection; + } else if (!strcmp((char*)Buf, "date-ordinal")) { + pTpe->data.field.eDateFormat = tplFmtOrdinal; } else if(!strcmp((char*)Buf, "lowercase")) { pTpe->data.field.eCaseConv = tplCaseConvLower; } else if(!strcmp((char*)Buf, "uppercase")) { @@ -1591,6 +1593,8 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o) datefmt = tplFmtTZOffsMin; } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"tzoffsdirection", sizeof("tzoffsdirection")-1)) { datefmt = tplFmtTZOffsDirection; + } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"ordinal", sizeof("ordinal")-1)) { + datefmt = tplFmtOrdinal; } else { uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL); errmsg.LogError(0, RS_RET_ERR, "invalid date format '%s' for property", diff --git a/template.h b/template.h index bbf230a09..95ff2faeb 100644 --- a/template.h +++ b/template.h @@ -63,7 +63,7 @@ enum tplFormatTypes { tplFmtDefault = 0, tplFmtMySQLDate = 1, tplFmtWDayName = 8, tplFmtYear = 9, tplFmtMonth = 10, tplFmtDay = 11, tplFmtHour = 12, tplFmtMinute = 13, tplFmtSecond = 14, tplFmtTZOffsHour = 15, tplFmtTZOffsMin = 16, tplFmtTZOffsDirection = 17, - tplFmtWDay = 18}; + tplFmtWDay = 18, tplFmtOrdinal = 19}; enum tplFormatCaseConvTypes { tplCaseConvNo = 0, tplCaseConvUpper = 1, tplCaseConvLower = 2 }; enum tplRegexType { TPL_REGEX_BRE = 0, /* posix BRE */ TPL_REGEX_ERE = 1 /* posix ERE */