I use a software program to manage my finances. Once a month I download a list of transactions for the previous month from my bank and my credit cards. The websites for these institutions allow me to specify a date range, and then download a QFX file that contains all the transactions within that range.
Except for americanexpress.com. Their website only lets me specify a one month range that corresponds to my account's billing cycle.
So, for my half-dozen bank accounts, and my Visa credit card, I can download a QFX file that contains transactions from the beginning of the month to the end of the month. But for Amex I have to download two months of data, from the 9th of the month before, to the 8th of the month after. Or thereabouts.
Big pain in the ass when you're trying to import transactions quickly, because you have to go in and either match transactions or delete duplicates. Yes, I could make all the QFX files correspond to the Amex card's billing cycle, but will only work as long as all the other websites are flexible, and makes keeping a month to month budget more difficult.
So, I wrote a Perl script that will take a QFX file, remove transactions that fall outside a specified range, and then output the remaining transactions to a new file.
(I added a feature that will preserve transactions that fall too far outside of the specified range, in case something weird is going on with the institution's billing. This tolerance can be tuned.)
This script is barely tested, isn't annotated, and probably isn't the most efficient way to do the job. So I don't make any guarantees. If you are actually reading this, and actually want to use the script -- which is about as likely Paris Hilton becoming a nun, or Oprah getting down to a size 2 -- you do so at your own risk.
That said, thar she blows ... (the script, not Oprah) ...
#! /usr/bin/perl
use Time::Local;
$usage = "
USAGE: qfix.pl filename lowdate highdate
DATE FORMAT: MMDDYY
EXAMPLE: qfix file.qfx 010109 013109
";
$infile = $ARGV[0];
$lowdate = $ARGV[1];
$highdate = $ARGV[2];
$lowtol = 31 * 24 * 60 * 60; # days * hr/day * mins/hr * secs/min
$hightol = 30 * 24 * 60 * 60;
$outfile = "$infile.$lowdate-$highdate";
unless ($#ARGV == 2) { die "$usage\n"; };
$ARGV[1] =~ m|\A(\d{2})(\d{2})(\d{2})|;
$lowdate = timelocal(0,0,0,$2,${1}-1,"20$3");
$ARGV[2] =~ m|\A(\d{2})(\d{2})(\d{2})|;
$highdate = timelocal(0,0,0,$2,${1}-1,"20$3");
if ($lowdate > $highdate) { die "$usage\n"; };
open (IFH, "<$infile") or die "Could not open input file $infile\n";
open (OFH, ">$outfile") or die "Could not open output file $outfile\n";
$intag = 0;
$inTHEtag = 0;
$tag = "";
while (read (IFH, $newchar, 1)){
if ($newchar =~ m|\<|) { $brack = 1 }
elsif ($newchar =~ m|\>|) { $brack = 2 }
else { $brack = 0 };
unless ($intag == 1) {
unless ($brack == 1) {
print OFH $newchar;
} else {
$intag = 1;
$tag .= $newchar;
};
} else {
$tag .= $newchar;
unless ($inTHEtag == 1) {
if ($brack == 2) {
unless ($tag =~ m|^\$|) { $|) {
print OFH "$tag";
$tag = "";
$intag = 0;
} else {
$inTHEtag = 1;
};
};
} else {
if ($brack == 2) {
if ($tag =~ m|\
if ($tag =~ m|\(\d{4})(\d{2})(\d{2})|) {
$transdate = timelocal(0,0,0,$3,${2}-1,$1);
#print OFH "$tag " . scalar(localtime($transdate)) . " XXX";
};
$lowdif = $transdate - $lowdate;
$highdif = $highdate - $transdate;
if (
(($transdate >= $lowdate) &&
($transdate <= $highdate)) ||
($transdate < ($lowdate - $lowtol)) ||
($transdate > ($highdate + $hightol))
) {
print OFH $tag;
};
$tag = "";
$intag = 0;
$inTHEtag = 0;
};
};
};
};
};
close IFH;
close OFH;
No comments:
Post a Comment