Thread: binary timestamp conversion
Hi all,
A few thousand rows have been deleted by accident in one of our databases.
I immediately disabled autovacuum and recovered the missing rows using pgfsck, a PostgreSQL table checker and dumper.
pgfsck can be found here:
http://svana.org/kleptog/pgsql/pgfsck.html
I am now facing a puzzling challenge: converting binary timestamp data! If pgfsck did properly recover the timestamp data as a binary string, pgfsck will use a default timestamp, “1900-01-01 00:00:00”, presumably because the date/time encoding varies from platform to platform.
Being on a FreeBSD box, and having PostgreSQL compiled with default options, I am assuming timestamps are encoded as long long (a signed long for the date and an unsigned long for the time).
I trying to unpack the string with Perl:
use strict;
my $t;
my $dt = '\xeb8^Ru^R^K\xb2A';
my @t = unpack( "Ll", $dt );
print $t[0] . "\n";
print $t[1] . "\n";
What I get is:
1650817116
1968332344
That is where I am being kind of… stuck…
I would have guessed that $t[1] is the number of microseconds since 2001-01-01… but what about $t[0]… it can’t be microseconds…
I had the idea to convert the binary timestamp using unpack and gmtime:
my @d = gmtime(946684800 + (($t[1] + $t[0]) / 1000000));
sprintf "%04d-%02d-%02d %02d:%02d:%02d", $d[5]+1900, $d[4]+1, $d[3], $d[2], $d[1], $d[0];
946684800 being the number of seconds from 1970-01-01 and 2001-01-01…
Any idea would be greatly appreciated!
De bedste hilsner / Best regards
David De Maeyer
Developer / System Architect
-------------------------------------------
web | : | |
: | ||
phone | : | (+45) 3910 1000 |
mobile | : | (+45) 2724 6077 |
fax | : | (+45) 3910 1001 |
ADNUVO°
Kompagnistræde 34
1208 Copenhagen K
Denmark
-------------------------------------------
David De Maeyer wrote: > I am now facing a puzzling challenge: converting binary timestamp > data! If pgfsck did properly recover the timestamp data as a binary > string, pgfsck will use a default timestamp, "1900-01-01 00:00:00", > presumably because the date/time encoding varies from platform to > platform. There are two representations, one using 64 bit integers and the other using floating point. Which one is your installation using depends on compile-time settings. -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
On Mon, Aug 17, 2009 at 11:35:41AM +0200, David De Maeyer wrote: > Being on a FreeBSD box, and having PostgreSQL compiled with default > options, I am assuming timestamps are encoded as long long (a signed > long for the date and an unsigned long for the time). Integer timestamps are the number of microseconds since 2000-01-01, otherwise it's a double representing the number of seconds since the same date. I don't know perl well enough to know if what you're doing is the right thing, but the values you're getting out don't look right to me. -- Sam http://samason.me.uk/