/**
   * Make sure that dates with and without millis can be converted properly into strings
   *
   * @throws Exception If there is an exception during the test
   */
  public void testFromDate() throws Exception {
    // I sure hope this works in other timezones...
    TimeZone.setDefault(TimeZone.getTimeZone("PST"));
    final Date date = new Date(123456789012345L);
    Assert.assertEquals("5882-03-11T00:30:12.345Z", ISO8601.fromDate(date));

    final Date dateNoMillis = new Date(123456789012000L);
    Assert.assertEquals("5882-03-11T00:30:12.000Z", ISO8601.fromDate(dateNoMillis));
  }
  /**
   * Make sure that dates in string format with and without millis can be converted properly into
   * date objects
   *
   * @throws Exception If there is an exception during the test
   */
  public void testToDate() throws Exception {
    TimeZone.setDefault(TimeZone.getTimeZone("PST"));
    final long toTheSecondDate = 123456789012000L;
    final Date dateToSecond = ISO8601.toDate("5882-03-11T00:30:12Z");
    Assert.assertEquals(toTheSecondDate, dateToSecond.getTime());

    final long toTheMillisecondDate = 123456789012345L;
    final Date dateToTheMillisecond = ISO8601.toDate("5882-03-11T00:30:12.345Z");
    Assert.assertEquals(toTheMillisecondDate, dateToTheMillisecond.getTime());

    final Date dateToTheExtremeMillisecond = ISO8601.toDate("5882-03-11T00:30:12.3456789Z");
    Assert.assertEquals(toTheMillisecondDate, dateToTheExtremeMillisecond.getTime());
  }
  public static String toISO8601(final Date date) {

    final Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    return ISO8601.format(calendar);
  }
 public static String toISO8601(final Calendar calendar) {
   return ISO8601.format(calendar);
 }
    @Override
    protected Boolean doInBackground(Integer... params) {

      List<JSONObject> transactions = new ArrayList<JSONObject>();
      Map<String, JSONObject> transfers = null;
      String currentUserId = null;
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mParent);
      int activeAccount = prefs.getInt(Constants.KEY_ACTIVE_ACCOUNT, -1);

      int startPage = (params.length == 0 || params[0] == null) ? 0 : params[0];
      int loadedPage;

      // Make API call to download list of transactions
      try {

        int numPages = 1; // Real value will be set after first list iteration
        loadedPage = startPage;

        // Loop is required to sync all pages of transaction history
        for (int i = startPage + 1; i <= startPage + Math.min(numPages, MAX_PAGES); i++) {

          List<BasicNameValuePair> getParams = new ArrayList<BasicNameValuePair>();
          getParams.add(new BasicNameValuePair("page", Integer.toString(i)));
          JSONObject response =
              RpcManager.getInstance().callGet(mParent, "transactions", getParams);

          currentUserId = response.getJSONObject("current_user").getString("id");

          JSONArray transactionsArray = response.optJSONArray("transactions");
          numPages = response.getInt("num_pages");

          if (transactionsArray == null) {
            // No transactions
            continue;
          }

          for (int j = 0; j < transactionsArray.length(); j++) {

            JSONObject transaction =
                transactionsArray.getJSONObject(j).getJSONObject("transaction");
            transactions.add(transaction);
          }

          loadedPage++;
        }

        if (startPage == 0) {
          transfers = fetchTransferData();
        }

        mMaxPage = numPages;

      } catch (IOException e) {
        Log.e("Coinbase", "I/O error refreshing transactions.");
        e.printStackTrace();

        return false;
      } catch (JSONException e) {
        // Malformed response from Coinbase.
        Log.e(
            "Coinbase",
            "Could not parse JSON response from Coinbase, aborting refresh of transactions.");
        ACRA.getErrorReporter().handleException(new RuntimeException("SyncTransactions", e));
        e.printStackTrace();

        return false;
      }

      DatabaseObject db = DatabaseObject.getInstance();

      synchronized (db.databaseLock) {
        db.beginTransaction(mParent);
        try {

          if (startPage == 0) {
            // Remove all old transactions
            db.delete(
                mParent,
                TransactionEntry.TABLE_NAME,
                TransactionEntry.COLUMN_NAME_ACCOUNT + " = ?",
                new String[] {Integer.toString(activeAccount)});
          }

          // Update user ID
          Editor editor = prefs.edit();
          editor.putString(String.format(Constants.KEY_ACCOUNT_ID, activeAccount), currentUserId);
          editor.commit();

          for (JSONObject transaction : transactions) {

            ContentValues values = new ContentValues();

            String createdAtStr = transaction.optString("created_at", null);
            long createdAt;
            try {
              if (createdAtStr != null) {
                createdAt = ISO8601.toCalendar(createdAtStr).getTimeInMillis();
              } else {
                createdAt = -1;
              }
            } catch (ParseException e) {
              // Error parsing createdAt
              e.printStackTrace();
              createdAt = -1;
            }

            JSONObject transferData = null;

            if (transfers != null) {

              String id = transaction.optString("id");
              transferData = transfers.get(id);
            }

            values.put(TransactionEntry._ID, transaction.getString("id"));
            values.put(TransactionEntry.COLUMN_NAME_JSON, transaction.toString());
            values.put(TransactionEntry.COLUMN_NAME_TIME, createdAt);
            values.put(TransactionEntry.COLUMN_NAME_ACCOUNT, activeAccount);
            values.put(
                TransactionEntry.COLUMN_NAME_TRANSFER_JSON,
                transferData == null ? null : transferData.toString());
            values.put(TransactionEntry.COLUMN_NAME_IS_TRANSFER, transferData == null ? 0 : 1);

            db.insert(mParent, TransactionEntry.TABLE_NAME, null, values);
          }

          db.setTransactionSuccessful(mParent);
          mLastLoadedPage = loadedPage;

          // Update list
          loadTransactionsList();

          // Update transaction widgets
          updateWidgets();

          // Update the buy / sell history list
          mParent.getBuySellFragment().onTransactionsSynced();

          return true;

        } catch (JSONException e) {
          // Malformed response from Coinbase.
          Log.e(
              "Coinbase",
              "Could not parse JSON response from Coinbase, aborting refresh of transactions.");
          e.printStackTrace();

          return false;
        } finally {

          db.endTransaction(mParent);
        }
      }
    }