Skip to content

Commit

Permalink
Merge pull request #13 from maciejlach/master
Browse files Browse the repository at this point in the history
Rewrite toString/fromString for QTimespan and QTimestamp.
  • Loading branch information
SKolodynski authored Feb 17, 2019
2 parents 0f37321 + 4789b8c commit 99a55c9
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 54 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
------------------------------------------------------------------------------
qJava 2.3.2 [2017.xx.xx]
------------------------------------------------------------------------------

- fix: fromString()/toString() conversion for temporal types

------------------------------------------------------------------------------
qJava 2.3.1 [2015.12.07]
------------------------------------------------------------------------------
Expand Down
159 changes: 132 additions & 27 deletions src/main/java/com/exxeleron/qjava/QTimespan.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,17 @@
package com.exxeleron.qjava;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
* Represents q timespan type.
*/
public final class QTimespan implements DateTime, Serializable {

private static final long serialVersionUID = 762296525233866140L;

private static final String NULL_STR = "0Nn";

private static final DateFormat dateFormat = new SimpleDateFormat("'D'HH:mm:ss.SSS");
private static final NumberFormat nanosFormatter = new DecimalFormat("000000");
private static final int NANOS_PER_SECOND = 1000000;
private static final long NANOS_PER_DAY = Utils.DAY_MILLIS * 1000000;
static final String NULL_STR = "0Nn";

private transient Date datetime;
private final Long value;
Expand All @@ -52,8 +44,8 @@ public QTimespan(final Long value) {
private static long getNanos( final Date datetime ) {
final Calendar c = Calendar.getInstance();
c.setTime(datetime);
return (long) (c.get(Calendar.MILLISECOND) + 1000 * c.get(Calendar.SECOND) + 60000 * c.get(Calendar.MINUTE) + 3600000 * c.get(Calendar.HOUR_OF_DAY))
* NANOS_PER_SECOND;
return (c.get(Calendar.MILLISECOND) + 1000 * c.get(Calendar.SECOND) + 60000 * c.get(Calendar.MINUTE) + 3600000 * c.get(Calendar.HOUR_OF_DAY))
* Utils.NANOS_PER_MILLI;
}

/**
Expand Down Expand Up @@ -87,7 +79,7 @@ public Long getValue() {
*/
public Date toDateTime() {
if ( datetime == null && value != Long.MIN_VALUE ) {
datetime = new Date(Utils.tzOffsetToQ(Math.abs(value) / NANOS_PER_SECOND + Utils.QEPOCH_MILLIS));
datetime = new Date(Utils.tzOffsetToQ(Math.abs(value) / Utils.NANOS_PER_MILLI + Utils.QEPOCH_MILLIS));
}
return datetime;
}
Expand All @@ -101,8 +93,62 @@ public Date toDateTime() {
@Override
public String toString() {
final Date dt = toDateTime();
return dt == null ? NULL_STR : (value < 0 ? "-" : "") + (Math.abs(value) / NANOS_PER_DAY) + getDateformat().format(dt)
+ getNanosformat().format(Math.abs(value) % NANOS_PER_SECOND);

if ( dt == null ) {
return NULL_STR;
} else {
final StringBuilder buffer = new StringBuilder(30);
final String zeros = "000000000";

if ( value < 0 ) {
buffer.append('-');
}
final long absValue = value < 0 ? -value : value;
final int days = ((int) (absValue / Utils.NANOS_PER_DAY));
buffer.append(days);
buffer.append('D');

final int hour = (int) ((absValue % Utils.NANOS_PER_DAY) / Utils.NANOS_PER_HOUR);
final int minute = (int) ((absValue % Utils.NANOS_PER_HOUR) / Utils.NANOS_PER_MINUTE);
final int second = (int) ((absValue % Utils.NANOS_PER_MINUTE) / Utils.NANOS_PER_SECOND);
final int nanos = (int) (absValue % Utils.NANOS_PER_SECOND);
String hourString;
String minuteString;
String secondString;
String nanosString;

if ( hour < 10 ) {
hourString = "0" + hour;
} else {
hourString = Integer.toString(hour);
}
if ( minute < 10 ) {
minuteString = "0" + minute;
} else {
minuteString = Integer.toString(minute);
}
if ( second < 10 ) {
secondString = "0" + second;
} else {
secondString = Integer.toString(second);
}
if ( nanos == 0 ) {
nanosString = zeros;
} else {
nanosString = Integer.toString(nanos);
nanosString = zeros.substring(0, (9 - nanosString.length())) + nanosString;
}

buffer.append(hourString);
buffer.append(':');
buffer.append(minuteString);
buffer.append(':');
buffer.append(secondString);
buffer.append('.');
buffer.append(nanosString);

return buffer.toString();
}
}

/**
Expand Down Expand Up @@ -147,23 +193,82 @@ public int hashCode() {
*/
public static QTimespan fromString( final String date ) {
try {
if ( date == null || date.length() == 0 || date.equals(NULL_STR) ) {
if ( date == null || date.length() == 0 || date.equals(QTimespan.NULL_STR) ) {
return new QTimespan(Long.MIN_VALUE);
} else {
final long nanos = getNanos(getDateformat().parse(date.substring(date.indexOf("D"), date.lastIndexOf(".") + 3)))
+ getNanosformat().parse(date.substring(date.lastIndexOf(".") + 3)).longValue();
return new QTimespan(Integer.valueOf(date.substring(0, date.indexOf("D"))) * NANOS_PER_DAY + ('-' == date.charAt(0) ? -1 : 1) * nanos);
final String formatError = "Timespan format must be [-]dDhh:mm:ss.fffffffff";
final String zeros = "000000000";

String date_s;
String time_s;
String nanos_s;
int day = 0;
int hour;
int minute;
int second;
int a_nanos = 0;

// Split the string into date and time components
final String s = date.trim();
final int dividingCharacter = s.indexOf('D');
if ( dividingCharacter > 0 ) {
date_s = s.substring(0, dividingCharacter);
time_s = s.substring(dividingCharacter + 1);
} else {
throw new java.lang.IllegalArgumentException(formatError);
}

// Parse the time
if ( time_s == null ) {
throw new java.lang.IllegalArgumentException(formatError);
}

final int firstDigit = date_s.indexOf('-') + 1;
final int firstColon = time_s.indexOf(':');
final int secondColon = time_s.indexOf(':', firstColon + 1);
final int period = time_s.indexOf('.', secondColon + 1);

// Convert the date
final boolean is_negative = firstDigit > 0;

if ( date_s.length() >= 0 ) {
final String day_s = date_s.substring(firstDigit);
day = Integer.parseInt(day_s);
} else {
throw new java.lang.IllegalArgumentException(formatError);
}

// Convert the time
if ( (firstColon > 0) & (secondColon > 0) & (secondColon < time_s.length() - 1) ) {
hour = Integer.parseInt(time_s.substring(0, firstColon));
minute = Integer.parseInt(time_s.substring(firstColon + 1, secondColon));
if ( (period > 0) & (period < time_s.length() - 1) ) {
second = Integer.parseInt(time_s.substring(secondColon + 1, period));
nanos_s = time_s.substring(period + 1);
if ( nanos_s.length() > 9 ) {
throw new java.lang.IllegalArgumentException(formatError);
}
if ( !Character.isDigit(nanos_s.charAt(0)) ) {
throw new java.lang.IllegalArgumentException(formatError);
}
nanos_s = nanos_s + zeros.substring(0, 9 - nanos_s.length());
a_nanos = Integer.parseInt(nanos_s);
} else if ( period > 0 ) {
throw new java.lang.IllegalArgumentException(formatError);
} else {
second = Integer.parseInt(time_s.substring(secondColon + 1));
}
} else {
throw new java.lang.IllegalArgumentException(formatError);
}

final long nanos = day * Utils.NANOS_PER_DAY + hour * Utils.NANOS_PER_HOUR + minute * Utils.NANOS_PER_MINUTE
+ second * Utils.NANOS_PER_SECOND + a_nanos;
return new QTimespan((is_negative ? -1 : 1) * nanos);
}
} catch ( final Exception e ) {
} catch (final Exception e) {
throw new IllegalArgumentException("Cannot parse QTimespan from: " + date, e);
}
}

private static DateFormat getDateformat() {
return (DateFormat) dateFormat.clone();
}

private static NumberFormat getNanosformat() {
return (NumberFormat) nanosFormatter.clone();
}
}
Loading

0 comments on commit 99a55c9

Please sign in to comment.