1Dateutils 2========= 3 4[![Build Status](https://secure.travis-ci.org/hroptatyr/dateutils.png?branch=master)](http://travis-ci.org/hroptatyr/dateutils) 5[![Build Status](https://drone.io/github.com/hroptatyr/dateutils/status.png)](https://drone.io/github.com/hroptatyr/dateutils/latest) 6[![Coverity Scan Build Status](https://scan.coverity.com/projects/2197/badge.svg)](https://scan.coverity.com/projects/2197) 7 8Dateutils are a bunch of tools that revolve around fiddling with dates 9and times on the command line with a strong focus on use cases that 10arise when dealing with large amounts of financial data. 11 12Dateutils are hosted primarily on github: 13 14+ github page: <https://github.com/hroptatyr/dateutils> 15+ project homepage: <http://www.fresse.org/dateutils/> 16+ downloads: <https://bitbucket.org/hroptatyr/dateutils/downloads> 17 18Below is a short list of examples that demonstrate what dateutils can 19do, for full specs refer to the info and man pages. For installation 20instructions refer to the INSTALL file. 21 22Dateutils commands are prefixed with a `date` but otherwise resemble 23known unix commands for reasons of intuition. The only exception being 24`strptime` which is analogous to the libc function of the same name. 25 26+ `strptime` Command line version of the C function 27+ `dateadd` Add durations to dates or times 28+ `dateconv` Convert dates or times between calendars 29+ `datediff` Compute durations between dates or times 30+ `dategrep` Grep dates or times in input streams 31+ `dateround` Round dates or times to "fuller" values 32+ `dateseq` Generate sequences of dates or times 33+ `datesort` Sort chronologically. 34+ `datetest` Compare dates or times 35+ `datezone` Convert date/times to timezones in bulk 36 37 38 39Examples 40======== 41 42I love everything explained by example to get a first impression. 43So here it comes. 44 45dateseq 46------- 47 A tool mimicking seq(1) but whose inputs are from the domain of dates 48 rather than integers. Typically scripts use something like 49 50 $ for i in $(seq 0 9); do 51 date -d "2010-01-01 +${i} days" "+%F" 52 done 53 54 which now can be shortened to 55 56 $ dateseq 2010-01-01 2010-01-10 57 58 with the additional benefit that the end date can be given directly 59 instead of being computed from the start date and an interval in 60 days. Also, it provides date specific features that would be a PITA 61 to implement using the above seq(1)/date(1) approach, like skipping 62 certain weekdays: 63 64 $ dateseq 2010-01-01 2010-01-10 --skip sat,sun 65 => 66 2010-01-01 67 2010-01-04 68 2010-01-05 69 2010-01-06 70 2010-01-07 71 2010-01-08 72 73 dateseq also works on times: 74 75 $ dateseq 12:00:00 5m 12:17:00 76 => 77 12:00:00 78 12:05:00 79 12:10:00 80 12:15:00 81 82 and also date-times: 83 84 $ dateseq --compute-from-last 2012-01-02T12:00:00 5m 2012-01-02T12:17:00 85 => 86 2012-01-02T12:02:00 87 2012-01-02T12:07:00 88 2012-01-02T12:12:00 89 2012-01-02T12:17:00 90 91dateconv 92-------- 93 A tool to convert dates between different calendric systems and/or 94 time zones. While other such tools usually focus on converting 95 Gregorian dates to, say, the Chinese calendar, dconv aims at 96 supporting calendric systems which are essential in financial 97 contexts. 98 99 To convert a (Gregorian) date into the so called ymcw representation: 100 101 $ dateconv 2012-03-04 -f "%Y-%m-%c-%w" 102 => 103 2012-03-01-00 104 105 and vice versa: 106 107 $ dateconv 2012-03-01-Sun -i "%Y-%m-%c-%a" -f '%F' 108 => 109 2012-03-04 110 111 where the ymcw representation means, the `%c`-th `%w` of the month in 112 a given year. This is useful if dates are specified like, the third 113 Thursday in May for instance. 114 115 dateconv can also be used to convert occurrences of dates, times or 116 date-times in an input stream on the fly 117 118 $ dateconv -S -i '%b/%d %Y at %I:%M %P' <<EOF 119 Remember we meet on Mar/03 2012 at 02:30 pm 120 EOF 121 => 122 Remember we meet on 2012-03-03T14:30:00 123 124 and most prominently to convert between time zones: 125 126 $ dateconv --from-zone "America/Chicago" --zone "Asia/Tokyo" 2012-01-04T09:33:00 127 => 128 2012-01-05T00:33:00 129 130 $ dateconv --zone "America/Chicago" now -f "%d %b %Y %T" 131 => 132 05 Apr 2012 11:11:57 133 134datetest 135-------- 136 A tool to perform date comparison in the shell, it's modelled after 137 `test(1)` but with proper command line options. 138 139 $ if datetest today --gt 2010-01-01; then 140 echo "yes" 141 fi 142 => 143 yes 144 145dateadd 146------- 147 A tool to perform date arithmetic (date maths) in the shell. Given 148 a date and a list of durations this will compute new dates. Given a 149 duration and a list of dates this will compute new dates. 150 151 $ dateadd 2010-02-02 +4d 152 => 153 2010-02-06 154 155 $ dateadd 2010-02-02 +1w 156 => 157 2010-02-09 158 159 $ dateadd -1d <<EOF 160 2001-01-05 161 2001-01-01 162 EOF 163 => 164 2001-01-04 165 2000-12-31 166 167 Adding durations to times: 168 169 $ dateadd 12:05:00 +10m 170 => 171 12:15:00 172 173 and even date-times: 174 175 $ dateadd 2012-03-12T12:05:00 -1d4h 176 => 177 2012-03-11T08:05:00 178 179 If supported by the system's zoneinfo database leap-second adjusted 180 calculations are possible. Use the unit `rs` to denote "real" seconds: 181 182 $ dateadd '2012-06-30 23:59:30' +30rs 183 => 184 2012-06-30T23:59:60 185 186 as opposed to: 187 188 $ dateadd '2012-06-30 23:59:30' +30s 189 => 190 2012-07-01T00:00:00 191 192datediff 193-------- 194 A tool to calculate the difference between two (or more) dates. This 195 is somewhat the converse of dadd. Outputs will be durations that, 196 when added to the first date, give the second date. 197 198 Get the number of days between two dates: 199 200 $ datediff 2001-02-08 2001-03-02 201 => 202 22 203 204 The duration format can be controlled through the `-f` switch: 205 206 $ datediff 2001-02-08 2001-03-09 -f "%m month and %d day" 207 => 208 1 month and 1 day 209 210 datediff also accepts time stamps as input: 211 212 $ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 213 => 214 92580s 215 216 The `-f` switch does the right thing: 217 218 $ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 -f '%dd %Ss' 219 => 220 1d 6180s 221 222 compare to: 223 224 $ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 -f '%dd %Hh %Ss' 225 => 226 1d 1h 2580s 227 228 If supported by the system's zoneinfo database leap-second adjusted 229 calculations can be made. Use the format specifier `%rS` to get the 230 elapsed time in "real" seconds: 231 232 datediff '2012-06-30 23:59:30' '2012-07-01 00:00:30' -f '%rS' 233 => 234 61 235 236dategrep 237-------- 238 A tool to extract lines from an input stream that match certain 239 criteria, showing either the line or the match: 240 241 $ dategrep '<2012-03-01' <<EOF 242 Feb 2012-02-28 243 Feb 2012-02-29 leap day 244 Mar 2012-03-01 245 Mar 2012-03-02 246 EOF 247 => 248 Feb 2012-02-28 249 Feb 2012-02-29 leap day 250 251dateround 252--------- 253 A tool to "round" dates or time stamps to a recurring point in time, 254 like the next/previous January or the next/previous Thursday. 255 256 Round (backwards) to the first of the current month: 257 258 $ dateround '2011-08-22' -1 259 => 260 2011-08-01 261 262 Find the next Monday from the current date (today is 2016-01-08): 263 264 $ dateround today Mon 265 => 266 2015-01-11 267 268 Go back to last September, then round to the end of the month: 269 270 $ dateround today -- -Sep +31d 271 => 272 2015-09-30 273 274 Round a stream of dates strictly to the next month's first: 275 276 $ dateround -S -n 1 <<EOF 277 pay cable 2012-02-28 278 pay gas 2012-02-29 279 pay rent 2012-03-01 280 redeem loan 2012-03-02 281 EOF 282 => 283 pay cable 2012-03-01 284 pay gas 2012-03-01 285 pay rent 2012-04-01 286 redeem loan 2012-04-01 287 288 Round a timeseries to the next minute (i.e. the seconds part is 00) 289 and then to the next half-past time (and convert to ISO): 290 291 $ dateround -S 0s30m -i '%d/%m/%Y %T' -f '%F %T' <<EOF 292 06/03/2012 14:27:12 eventA 293 06/03/2012 14:29:59 eventA 294 06/03/2012 14:30:00 eventB 295 06/03/2012 14:30:01 eventB 296 EOF 297 => 298 2012-03-06 14:30:00 eventA 299 2012-03-06 14:30:00 eventA 300 2012-03-06 14:30:00 eventB 301 2012-03-06 15:30:00 eventB 302 303 Alternatively, if you divide the day into half-hours you can round to 304 one of those using the co-class notation: 305 306 $ dateround -S /30m -i '%d/%m/%Y %T' -f '%F %T' <<EOF 307 06/03/2012 14:27:12 eventA 308 06/03/2012 14:29:59 eventA 309 06/03/2012 14:30:00 eventB 310 06/03/2012 14:30:01 eventB 311 EOF 312 => 313 2012-03-06 14:30:00 eventA 314 2012-03-06 14:30:00 eventA 315 2012-03-06 14:30:00 eventB 316 2012-03-06 15:00:00 eventB 317 318 This is largely identical to the previous example except, that a full 319 hour (being an even multiple of half-hours) is a possible rounding 320 target. 321 322 323datesort 324----- 325 A tool to bring the lines of a file into chronological order. 326 327 At the moment the `datesort` tool depends on `sort(1)` with support 328 for fields, in particular `-t` to select a separator and `-k` to sort 329 by a particular field. 330 331 $ datesort <<EOF 332 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 333 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 334 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" 335 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 336 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 337 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 338 EOF 339 => 340 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 341 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 342 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 343 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 344 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 345 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" 346 347 348datezone 349-------- 350 A tool to quickly inspect date/time values in different timezones. 351 The result will be a matrix that shows every date-time value in every 352 timezone: 353 354 $ datezone Europe/Berlin Australia/Sydney now 2014-06-30T05:00:00 355 => 356 2014-01-30T17:37:13+01:00 Europe/Berlin 357 2014-01-31T03:37:13+11:00 Australia/Sydney 358 2014-06-30T07:00:00+02:00 Europe/Berlin 359 2014-06-30T15:00:00+10:00 Australia/Sydney 360 361 The `datezone` tool can also be used to obtain the next or previous DST 362 transition relative to a given date/time: 363 364 $ datezone --next Europe/Berlin Australia/Sydney 2013-02-19 365 => 366 2013-03-31T02:00:00+01:00 -> 2013-03-31T03:00:00+02:00 Europe/Berlin 367 2013-04-07T03:00:00+11:00 -> 2013-04-07T02:00:00+10:00 Australia/Sydney 368 369 where the left time stamp denotes the current zone offset and the 370 right side is the zone offset after the transition. The date/time 371 indicates the exact moment when the transition is about to take 372 place. 373 374 In essence `datezone` is a better [`zdump(8)`][3]. 375 376 377strptime 378-------- 379 A tool that brings the flexibility of [`strptime(3)`][1] to the 380 command line. While (at least GNU) [`date(1)`][2] has support for 381 output formats, it lacks any kind of support to read arbitrary input 382 from the domain of dates, in particular when the input format is 383 specifically known beforehand and only matching dates/times shall be 384 considered. 385 386 With the `strptime` tool reading weird dates like `Mon, May-01/2000` 387 becomes a matter of 388 389 strptime -i "%a, %b-%d/%Y" "Mon, May-01/2000" 390 => 391 2000-05-01 392 393 just as you would have done in C. 394 395 Note that `strptime` actually uses the system libc's strptime routine, 396 and for output the system's strftime routine. Input and output 397 modifiers will therefore vary between systems. 398 399 For a portable parser/printer combination use `dateconv` as described 400 above. Its input and output format specifiers are independent of the 401 C runtime. 402 403 404Similar projects 405================ 406 407In no particular order and without any claim to completeness: 408 409+ dateexpr: <http://www.eskimo.com/~scs/src/#dateexpr> 410+ allanfalloon's dateutils: <https://github.com/alanfalloon/dateutils> 411+ yest <http://yest.sourceforge.net/> 412 413Use the one that best fits your purpose. And in case you happen to like 414mine, vote: [dateutils' openhub page](https://www.openhub.net/p/dateutils) 415 416 417 [1]: http://linux.die.net/man/3/strptime 418 [2]: http://linux.die.net/man/1/date 419 [3]: http://linux.die.net/man/8/zdump 420 421<!-- 422 Local variables: 423 mode: auto-fill 424 fill-column: 72 425 filladapt-mode: t 426 End: 427--> 428