// // Copyright 2020-2024 SenX S.A.S. // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, version 3. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see // { 'name' 'senx/cal/BUCKETIZE.bymonth' 'since' '2.4.1' 'tags' [ 'framework' 'bucketize' 'gts' 'bucketizer' 'cal' ] 'desc' <' Creates bucketized Geo Time Series with monthly buckets that start at the begining of a month. The lastbucket and the bucketcount are computed automatically. In the resulting series, the tick associated to each bucket is its month index (the number of months that are ended since Unix Epoch). For example, bucket 0 spans the interval ['1970-01-01T00:00:00.000000Z', '1970-01-31T23:59:59.999999Z'] (if the platform is configured with microseconds precision). Note that if the actual month has fewer than 31 days, the lastbucket will correspond to the next month with 31 days and will be empty (this is for calendar unbucketization purpose). Timestamp ticks can be restored using the macro UNBUCKETIZE.CALENDAR. In that case, each bucket's tick will be replaced by the last timestamp of their month. For more control on other parameters of the bucketization process, use instead BUCKETIZE.CALENDAR. '> 'sig' [ [ [ [ 'bucketizer:BUCKETIZER' 'gts:GTS+' ] ] [ 'result:LIST' ] ] [ [ [ 'macro:MACRO' 'gts:GTS+' ] ] [ 'result:LIST' ] ] [ [ [ 'timezone:STRING' 'bucketizer:BUCKETIZER' 'gts:GTS+' ] ] [ 'result:LIST' ] ] [ [ [ 'timezone:STRING' 'macro:MACRO' 'gts:GTS+' ] ] [ 'result:LIST' ] ] ] 'params' { 'gts' 'One or more Geo Time Series™ or lists of Geo Time Series™' 'bucketizer' 'Bucketizer function to apply' 'macro' 'Macro to apply. Must expect a GTS as input. Must push onto the stack either [value], or [tick,value], or [tick,elev,value], or [tick,lat,lon,value], or [tick,lat,lon,elev,value], or tick, lat, lon, elev and value.' 'timezone' 'The timezone to consider. Default to UTC' 'result' 'List of bucketized GTS in the new time referential' } 'related' [ 'BUCKETIZE.CALENDAR' 'BUCKETIZE' 'UNBUCKETIZE.CALENDAR' '@senx/cal/BUCKETIZE.byyear' ] 'examples' [ <' [ 2019 ] TSELEMENTS-> 'end' STORE NEWGTS 1 2000 <% $end SWAP -1 * ADDDAYS NaN NaN NaN 1 ADDVALUE %> FOR [ SWAP bucketizer.count ] @senx/cal/BUCKETIZE.bymonth UNBUCKETIZE.CALENDAR '> ] } 'info' STORE <% !$info INFO SAVE 'context' STORE // handle optional timezone REVERSE 0 REMOVE DUP TYPEOF 'STRING' == <% 'tz' STORE 0 REMOVE %> <% 'UTC' 'tz' STORE %> IFTE // handle bucketizer 'bucketizer' STORE $bucketizer TYPEOF 'MACRO' != $bucketizer TYPEOF 'MAPPER' != && $bucketizer TYPEOF 'AGGREGATOR' != && <% 'Expects a macro or a bucketizer after input GTS.' MSGFAIL %> IFT // apply monthly bucketize REVERSE FLATTEN <% DROP 'gts' STORE $gts SIZE 0 == <% // empty gts, return a calendar-bucketized gts bucketoffset is 0 [ $gts $bucketizer -1 'P1M' 0 $tz ] BUCKETIZE.CALENDAR %> <% // non empty gts $gts LASTTICK $tz ->TSELEMENTS [ 0 1 ] SUBLIST 'tselems' STORE // substracting a month to the last tick of a month does not always lands to the last tick of previous month // it works only if it is a month with 31 days // so if the month does not contain 31 days, we must use the next one as lastbucket $tselems LIST-> DROP [ 'y' 'm' ] STORE [ 1 3 5 7 8 10 12 ] $m CONTAINS SWAP DROP 'has31days' STORE $has31days NOT <% $m 1 + 'm' STORE %> IFT [ $y $m ] $tz TSELEMENTS-> $tz 1 ADDMONTHS 1 - 'lastbucket' STORE [ $gts $bucketizer $lastbucket 'P1M' 0 $tz ] BUCKETIZE.CALENDAR %> IFTE %> LFLATMAP $context RESTORE %>