/*
* Copyright 2006 Bradley Schatz. All rights reserved.
*
* This file is part of pasco2, the next generation Internet Explorer cache
* and history record parser.
*
* pasco2 is free software; you can redistribute it and/or modify
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* pasco2 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pasco2; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
package isi.pasco2.parser.time;
import isi.pasco2.parser.DateTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class FileTime implements DateTime{
static DateFormat xsdDateFormat = null;
static DateFormat regularDateFormat = null;
{
xsdDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
xsdDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
regularDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
regularDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
// the remainder in nanoseconds since the unix epoch
long remainderNanoSeconds;
// the number of seconds since the unix epoch
long time_t;
public long gettime_t() {
return time_t;
}
public long getRemainderNanoSeconds() {
return remainderNanoSeconds;
}
public long getTimeAsMillis() {
return time_t*1000 + (remainderNanoSeconds / 1000000);
}
public long getMillisRemainder() {
return remainderNanoSeconds / 1000000;
}
public long getMicrosRemainder() {
return remainderNanoSeconds % 1000000;
}
public Date asDate() {
return new Date(getTimeAsMillis());
}
private long low;
private long high;
public long getHigh() {
return high;
}
public long getLow() {
return low;
}
/**
* Create a parser for windows FILETIME timestamps. This is a count of the number
* of 100ns increments since the Epoch Jan 1 1601 at 00:00:00. Credits for the
* algorithm go to cygin's to_timestruc_t() implementation found in time.cc.
*
* @param low 32bit unsigned int low value of the timestamp, passed as a java long
* @param high 32bit unsigned int low value of the timestamp, passed as a java long
*/
public FileTime(long low, long high) {
this.low = low;
this.high = high;
parse(low, high);
}
// the number of 100 ns ticks between 00:00:00 on Jan 1, 1601 and 00:00:00 Jan 1, 1970
// validated in the unit test TestPlatform.testSkewBetweenUNIXEpochAndWindowsEpoch
static long skewFILETIME2timetEpochs = 0x19db1ded53e8000L;
static long ticksPerSecond = 10 * 1000 * 1000L;
/**
*
* this code is based on cygin's times.cc/to_timestruc_t(). Author not indicated.
*
*/
void parse(long low, long high) {
long rem;
long x = (high << 32) + (low);
/* return the UNIX epoch as the FILETIME epoch */
if (x == 0) {
time_t = 0;
rem = 0;
return;
}
x -= skewFILETIME2timetEpochs; // remove the skew so x now is the number of
// ticks since 00:00:00 1/1/1970
rem = x % ticksPerSecond; // remaining ticks not whole seconds
x /= ticksPerSecond; // number of seconds since UNIX epoch
remainderNanoSeconds = rem * 100; // as remainder is in nanoseconds
time_t = x;
}
public String toString() {
return xsdDateFormat.format(asDate());
}
public String toXSDString() {
return xsdDateFormat.format(asDate());
}
public String toStandardTime() {
return xsdDateFormat.format(asDate());
}
public static FileTime parseLittleEndianHex(String hex) {
assert hex.length() == 16;
long low = Long.parseLong(hex.substring(0,8) , 16);
low = ((low & 0xFF) << 24) | ((low & 0x0FF00) << 8) | ((low & 0xFF0000) >> 8) | ((low & 0xFF000000)>> 24);
long high = Long.parseLong(hex.substring(8,16) , 16);
high = ((high & 0xFF) << 24) | ((high & 0x0FF00) << 8) | ((high & 0xFF0000) >> 8) | ((high & 0xFF000000)>> 24);
return new FileTime(low,high);
}
public static FileTime parseBigEndianHex(String hex) {
assert hex.length() == 16;
long all = Long.parseLong(hex, 16);
long low = all & 0x0ffffffffL;
long high = (all & 0xffffffff00000000L) >> 32;
return new FileTime(low,high);
}
public boolean equals(Object obj) {
if (obj instanceof FileTime) {
FileTime f = (FileTime) obj;
if (f.time_t == this.time_t && f.remainderNanoSeconds == this.remainderNanoSeconds) {
return true;
}
}
return false;
}
}