3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-01 07:42:17 +00:00

Fix formatting dates at several places. Common mistakes:

- DateFormats are not thread safe
- new Date() is used for formatting which does not specify a locale

We now use a Utils.dateTimeFormat() helper for formatting to ISO 8601 (UTC).
This commit is contained in:
Andreas Schildbach 2014-11-07 21:55:17 +01:00
parent 28d0743dd6
commit e12930c00f
8 changed files with 59 additions and 26 deletions

View File

@ -1,5 +1,6 @@
/**
* Copyright 2011 Google Inc.
* Copyright 2014 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -588,7 +589,7 @@ public class Block extends Message {
s.append(" time: [");
s.append(time);
s.append("] ");
s.append(new Date(time * 1000));
s.append(Utils.dateTimeFormat(time * 1000));
s.append("\n");
s.append(" difficulty target (nBits): ");
s.append(difficultyTarget);

View File

@ -1,5 +1,6 @@
/**
* Copyright 2011 Google Inc.
* Copyright 2014 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,7 +20,6 @@ package org.bitcoinj.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.Semaphore;
@ -80,8 +80,8 @@ public class DownloadListener extends AbstractPeerEventListener {
* @param date the date of the last block downloaded
*/
protected void progress(double pct, int blocksSoFar, Date date) {
log.info(String.format("Chain download %d%% done with %d blocks to go, block date %s", (int) pct,
blocksSoFar, DateFormat.getDateTimeInstance().format(date)));
log.info(String.format("Chain download %d%% done with %d blocks to go, block date %s", (int) pct, blocksSoFar,
Utils.dateTimeFormat(date)));
}
/**

View File

@ -32,8 +32,6 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import static org.bitcoinj.core.Utils.*;
@ -1263,19 +1261,6 @@ public class Transaction extends ChildMessage implements Serializable {
return false;
}
/**
* Parses the string either as a whole number of blocks, or if it contains slashes as a YYYY/MM/DD format date
* and returns the lock time in wire format.
*/
public static long parseLockTimeStr(String lockTimeStr) throws ParseException {
if (lockTimeStr.indexOf("/") != -1) {
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
Date date = format.parse(lockTimeStr);
return date.getTime() / 1000;
}
return Long.parseLong(lockTimeStr);
}
/**
* Returns either the lock time as a date, if it was specified in seconds, or an estimate based on the time in
* the current head block if it was specified as a block time.

View File

@ -35,6 +35,8 @@ import java.math.BigInteger;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@ -444,6 +446,28 @@ public class Utils {
return currentTimeMillis() / 1000;
}
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
/**
* Formats a given date+time value to an ISO 8601 string.
* @param dateTime value to format, as a Date
*/
public static String dateTimeFormat(Date dateTime) {
DateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
iso8601.setTimeZone(UTC);
return iso8601.format(dateTime);
}
/**
* Formats a given date+time value to an ISO 8601 string.
* @param dateTime value to format, unix time (ms)
*/
public static String dateTimeFormat(long dateTime) {
DateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
iso8601.setTimeZone(UTC);
return iso8601.format(dateTime);
}
public static byte[] copyOf(byte[] in, int length) {
byte[] out = new byte[length];
System.arraycopy(in, 0, out, 0, Math.min(length, in.length));

View File

@ -1,5 +1,6 @@
/*
* Copyright 2013 Google Inc.
* Copyright 2014 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,7 +30,6 @@ import org.bitcoin.paymentchannel.Protos;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.ReentrantLock;
@ -66,8 +66,6 @@ public class PaymentChannelClient implements IPaymentChannelClient {
// The state object used to step through initialization and pay the server
@GuardedBy("lock") private PaymentChannelClientState state;
public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
// The step we are at in initialization, this is partially duplicated in the state object
private enum InitStep {
WAITING_FOR_CONNECTION_OPEN,
@ -180,7 +178,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
checkState( expireTime >= 0 && initiate.getMinAcceptedChannelSize() >= 0);
if (! conn.acceptExpireTime(expireTime)) {
log.error("Server suggested expire time was out of our allowed bounds: {} ({} s)", dateFormat.format(new Date(expireTime * 1000)), expireTime);
log.error("Server suggested expire time was out of our allowed bounds: {} ({} s)", Utils.dateTimeFormat(expireTime * 1000), expireTime);
errorBuilder.setCode(Protos.Error.ErrorCode.TIME_WINDOW_UNACCEPTABLE);
return CloseReason.TIME_WINDOW_UNACCEPTABLE;
}

View File

@ -1,5 +1,5 @@
/**
* Copyright 2013 The bitcoinj developers.
* Copyright 2014 The bitcoinj developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -1277,7 +1277,8 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
seed.toHexString())
);
}
builder2.append(String.format("Seed birthday: %d [%s]%n", seed.getCreationTimeSeconds(), new Date(seed.getCreationTimeSeconds() * 1000)));
builder2.append(String.format("Seed birthday: %d [%s]%n", seed.getCreationTimeSeconds(),
Utils.dateTimeFormat(seed.getCreationTimeSeconds() * 1000)));
}
final DeterministicKey watchingKey = getWatchingKey();
// Don't show if it's been imported from a watching wallet already, because it'd result in a weird/

View File

@ -1,5 +1,6 @@
/**
* Copyright 2011 Thilo Planz
* Copyright 2014 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,6 +18,8 @@
package org.bitcoinj.core;
import java.math.BigInteger;
import java.util.Date;
import org.junit.Test;
import static org.junit.Assert.*;
@ -52,4 +55,10 @@ public class UtilsTest {
assertEquals(0x05123456L, Utils.encodeCompactBits(new BigInteger("1234560000", 16)));
assertEquals(0x0600c0deL, Utils.encodeCompactBits(new BigInteger("c0de000000", 16)));
}
@Test
public void dateTimeFormat() {
assertEquals("2014-11-16T10:54:33Z", Utils.dateTimeFormat(1416135273781L));
assertEquals("2014-11-16T10:54:33Z", Utils.dateTimeFormat(new Date(1416135273781L)));
}
}

View File

@ -64,8 +64,10 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@ -561,7 +563,7 @@ public class WalletTool {
try {
if (lockTimeStr != null) {
t.setLockTime(Transaction.parseLockTimeStr(lockTimeStr));
t.setLockTime(parseLockTimeStr(lockTimeStr));
// For lock times to take effect, at least one output must have a non-final sequence number.
t.getInputs().get(0).setSequenceNumber(0);
// And because we modified the transaction after it was completed, we must re-sign the inputs.
@ -604,6 +606,19 @@ public class WalletTool {
}
}
/**
* Parses the string either as a whole number of blocks, or if it contains slashes as a YYYY/MM/DD format date
* and returns the lock time in wire format.
*/
private static long parseLockTimeStr(String lockTimeStr) throws ParseException {
if (lockTimeStr.indexOf("/") != -1) {
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
Date date = format.parse(lockTimeStr);
return date.getTime() / 1000;
}
return Long.parseLong(lockTimeStr);
}
private static void sendPaymentRequest(String location, boolean verifyPki) {
if (location.startsWith("http") || location.startsWith("bitcoin")) {
try {