Created
September 25, 2014 15:14
-
-
Save dragon66/e9b8fb13c657e12b7145 to your computer and use it in GitHub Desktop.
Java ISO8601 Utility
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright (c) 2014 by Wen Yu. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Any modifications to this file must keep this entire header intact. | |
*/ | |
package cafe.date; | |
import java.util.Calendar; | |
import java.util.Date; | |
import java.util.Locale; | |
import java.util.TimeZone; | |
import java.text.DateFormat; | |
import java.text.SimpleDateFormat; | |
/** | |
* A wrapper for the Date class with information for TimeZone, Locale as well | |
* as a calendar associated with it | |
* | |
* @author Wen Yu, [email protected] | |
* @version 1.0 02/15/2013 | |
*/ | |
public class DateTime | |
{ | |
private Date date; | |
private TimeZone timeZone; | |
private Locale locale; | |
private Calendar calendar; | |
public DateTime(Date date) { | |
this(date, TimeZone.getDefault(), Locale.getDefault()); | |
} | |
public DateTime(Date date, TimeZone timeZone, Locale locale) { | |
this.date = date; | |
this.timeZone = timeZone; | |
this.locale = locale; | |
this.calendar = Calendar.getInstance(timeZone, locale); | |
calendar.setTime(date); | |
} | |
public DateTime(Date date, TimeZone timeZone) { | |
this(date, timeZone, Locale.getDefault()); | |
} | |
public boolean after(DateTime that) { | |
return this.getUTCTimeInMillis() > that.getUTCTimeInMillis(); | |
} | |
public boolean before(DateTime that) { | |
return this.getUTCTimeInMillis() < that.getUTCTimeInMillis(); | |
} | |
/** | |
* Simple representation of the current date for the default TimeZone | |
* and Locale. | |
* | |
* @return a DateTime object for the default TimeZone and Locale. | |
*/ | |
public static DateTime currentDate() { | |
TimeZone tz = TimeZone.getDefault(); | |
Locale locale = Locale.getDefault(); | |
return currentDate(tz, locale); | |
} | |
public static DateTime currentDate(TimeZone timeZone) { | |
Locale locale = Locale.getDefault(); | |
return currentDate(timeZone, locale); | |
} | |
public static DateTime currentDate(TimeZone timeZone, Locale locale) { | |
Date date = new Date(); | |
return new DateTime(date, timeZone, locale); | |
} | |
public static DateTime currentDateUTC() { | |
return currentDate(TimeZone.getTimeZone("UTC")); | |
} | |
public static DateTime currentDateUTC(Locale locale) { | |
return currentDate(TimeZone.getTimeZone("UTC"), locale); | |
} | |
public DateTime dateAfter(int years, int months) { | |
Calendar clone = (Calendar)calendar.clone(); | |
clone.add(Calendar.YEAR, years); | |
clone.add(Calendar.MONTH, months); | |
return new DateTime(clone.getTime(), timeZone, locale); | |
} | |
public DateTime dateAfter(int years, int months, int days) { | |
Calendar clone = (Calendar)calendar.clone(); | |
clone.add(Calendar.YEAR, years); | |
clone.add(Calendar.MONTH, months); | |
clone.add(Calendar.DAY_OF_MONTH, days); | |
return new DateTime(clone.getTime(), timeZone, locale); | |
} | |
public DateTime dateAfter(int years, int months, int days, int hours, int minutes, int seconds, int millis) { | |
Calendar clone = (Calendar)calendar.clone(); | |
clone.add(Calendar.YEAR, years); | |
clone.add(Calendar.MONTH, months); | |
clone.add(Calendar.DAY_OF_MONTH, days); | |
clone.add(Calendar.HOUR, hours); | |
clone.add(Calendar.MINUTE, minutes); | |
clone.add(Calendar.SECOND, seconds); | |
clone.add(Calendar.MILLISECOND, millis); | |
return new DateTime(clone.getTime(), timeZone, locale); | |
} | |
public DateTime daysAfter(int days) { | |
return new DateTime(new Date(date.getTime() + 1000L*3600*24*days), timeZone, locale); | |
} | |
public boolean equals(Object that) { | |
if (!(that instanceof DateTime)) | |
return false; | |
return this.getUTCTimeInMillis() == ((DateTime)that).getUTCTimeInMillis(); | |
} | |
public String format(DateFormat df) { | |
return df.format(date); | |
} | |
public String format(String format) { | |
return format(format, Locale.getDefault()); | |
} | |
public String format(String format, Locale locale) { | |
DateFormat df = new SimpleDateFormat(format, (locale == null)?Locale.getDefault():locale); | |
df.setTimeZone(timeZone); | |
String dateString = df.format(date); | |
return dateString; | |
} | |
/** | |
* Formats a DateTime to a ISO8601 string with a second fraction part of up to 3 digits. | |
*/ | |
public String formatISO8601() { | |
return ISO8601DateUtils.formatISO8601(date, timeZone); | |
} | |
public Date getDate() { | |
return (Date)date.clone(); | |
} | |
public int getDayOfMonth() { | |
return calendar.get(Calendar.DAY_OF_MONTH); | |
} | |
public int getDayOfWeek() { | |
return calendar.get(Calendar.DAY_OF_WEEK); | |
} | |
public int getMonth() { | |
return calendar.get(Calendar.MONTH); | |
} | |
public long getUTCTimeInMillis() { | |
long time = date.getTime(); | |
int zoneOffset = timeZone.getOffset(time); | |
return time + zoneOffset; | |
} | |
public int getYear() { | |
return calendar.get(Calendar.YEAR); | |
} | |
public int hashCode() { | |
return Long.valueOf(getUTCTimeInMillis()).hashCode(); | |
} | |
public DateTime hoursAfter(int hours) { | |
return new DateTime(new Date(date.getTime() + 1000L*3600*hours), timeZone, locale); | |
} | |
public DateTime monthsAfter(int months) { | |
Calendar clone = (Calendar)calendar.clone(); | |
clone.add(Calendar.MONTH, months); | |
return new DateTime(clone.getTime(), timeZone, locale); | |
} | |
public String toString() { | |
DateFormat df = DateFormat.getInstance(); | |
df.setTimeZone(timeZone); | |
return df.format(this.date) + " " + timeZone.getDisplayName(); | |
} | |
public DateTime yearsAfter(int years) { | |
Calendar clone = (Calendar)calendar.clone(); | |
clone.add(Calendar.YEAR, years); | |
return new DateTime(clone.getTime(), timeZone, locale); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright (c) 2014 by Wen Yu. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Any modifications to this file must keep this entire header intact. | |
*/ | |
package cafe.date; | |
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.Date; | |
import java.util.TimeZone; | |
import cafe.date.DateTime; | |
import cafe.string.StringUtils; | |
/** | |
* http://www.w3.org/TR/NOTE-datetime | |
* | |
* The formats are as follows. Exactly the components shown here must be | |
* present, with exactly this punctuation. Note that the "T" appears literally | |
* in the string, to indicate the beginning of the time element, as specified in | |
* ISO 8601. | |
* | |
* Year: | |
* YYYY (eg 1997) | |
* Year and month: | |
* YYYY-MM (eg 1997-07) | |
* Complete date: | |
* YYYY-MM-DD (eg 1997-07-16) | |
* Complete date plus hours and minutes: | |
* YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) | |
* Complete date plus hours, minutes and seconds: | |
* YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) | |
* Complete date plus hours, minutes, seconds and a decimal fraction of a second | |
* YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) | |
* | |
* where: | |
* | |
* YYYY = four-digit year | |
* MM = two-digit month (01=January, etc.) | |
* DD = two-digit day of month (01 through 31) | |
* hh = two digits of hour (00 through 23) (am/pm NOT allowed) | |
* mm = two digits of minute (00 through 59) | |
* ss = two digits of second (00 through 59) | |
* s = one or more digits representing a decimal fraction of a second | |
* TZD = time zone designator (Z or +hh:mm or -hh:mm) | |
*/ | |
/** | |
* ISO 8601 date utilities. | |
* | |
* Supports up to 3 digits fraction of a second. | |
* | |
* @author Wen Yu, [email protected] | |
* @version 1.0 03/04/2013 | |
*/ | |
public class ISO8601DateUtils { | |
private ISO8601DateUtils() {} | |
/** | |
* Formats a DateTime to a ISO8601 string with a second fraction part of up to 3 digits. | |
*/ | |
public static String formatISO8601(Date date, TimeZone timeZone) { | |
SimpleDateFormat df = null; | |
if (timeZone != null) { | |
df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'SSSZ"); | |
df.setTimeZone(timeZone); | |
String result = df.format(date); | |
if (result.endsWith("0000")) | |
return result.replaceAll("[+-]0000$", "Z"); | |
return result.replaceAll("(\\d{2})(\\d{2})$", "$1:$2"); | |
} | |
df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); | |
return df.format(date); | |
} | |
/** | |
* Parses a ISO8601 string into a DateTime to retain time zone information. | |
* | |
* The pattern is dynamically created in accordance with the input date string. | |
* Time zone is optional. | |
* | |
* The fraction part of the second if exists is cut down to 3 digits, i.e to the | |
* precision of millisecond. | |
*/ | |
public static DateTime parse(String input) throws ParseException { | |
TimeZone timeZone = null; | |
StringBuilder sb = new StringBuilder(30); | |
String[] dateParts = {"yyyy", "yyyy-MM", "yyyy-MM-dd"}; | |
String[] timeParts = {"HH", "HH:mm", "HH:mm:ss"}; | |
String[] inputs = input.split("-"); | |
sb.append(dateParts[Math.min(inputs.length - 1, 2)]); | |
int timeIndex = input.indexOf("T"); | |
// If we have time parts | |
if (timeIndex > 0) | |
{ | |
input = input.replace("Z", "+00:00"); | |
boolean hasTimeZone = false; | |
int timeZoneLen = 0; | |
String timeStr = input.substring(timeIndex); | |
// If we have time zone | |
//if (StringUtils.contains(timeStr, "[+-]\\d{2}:\\d{2}$")) | |
if (timeStr.indexOf("+") > 0 || timeStr.indexOf("-") > 0) | |
{ | |
hasTimeZone = true; | |
timeZoneLen = 5; | |
timeZone = TimeZone.getTimeZone("GMT" + input.substring(input.length() - 6)); | |
input = StringUtils.replaceLast(input, ":", ""); | |
} | |
String[] timeInputs = input.split(":"); | |
sb.append("'T'"); | |
sb.append(timeParts[timeInputs.length - 1]); | |
int indexOfDot = input.indexOf("."); | |
if (indexOfDot > 0) { | |
sb.append("'.'"); | |
int secondFractionLen = input.length() - indexOfDot - 1 - timeZoneLen; | |
// cut to 3 digits, we avoid round up which may cause problem in case of carrying | |
if (secondFractionLen > 3) | |
{ | |
String secondFractionStr = input.substring(indexOfDot, indexOfDot + secondFractionLen + 1); | |
input = input.replace(secondFractionStr, input.substring(indexOfDot, indexOfDot + 4)); | |
} | |
for (int j = secondFractionLen; j > 0; j--) | |
{ | |
sb.append("S"); | |
} | |
} | |
if (hasTimeZone) | |
sb.append("Z"); | |
} | |
SimpleDateFormat df = new SimpleDateFormat(sb.toString()); | |
return new DateTime(df.parse(input), timeZone); | |
} | |
public static String format(Date date, String format) { | |
SimpleDateFormat df = new SimpleDateFormat(format); | |
return df.format(date); | |
} | |
public static String format(Date date) { | |
return format(date, "yyyy-MM-dd'T'HH:mm:ss.SSS"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright (c) 2014 by Wen Yu. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Any modifications to this file must keep this entire header intact. | |
*/ | |
package cafe.string; | |
import java.io.PrintWriter; | |
import java.io.StringWriter; | |
import java.io.UnsupportedEncodingException; | |
import java.net.URLEncoder; | |
import java.util.Iterator; | |
import java.util.NoSuchElementException; | |
import java.util.regex.*; | |
/** | |
* String utility class | |
* | |
* @author Wen Yu, [email protected] | |
* @version 1.0 09/18/2012 | |
*/ | |
public class StringUtils | |
{ | |
private static final char[] HEXES = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; | |
/** | |
* Formats byte array. | |
* | |
* @param bytes an array of byte. | |
* @return a hex string representation of the byte array. | |
*/ | |
public static String byteArrayToHexString(byte [] bytes) { | |
if ( bytes == null ) { | |
return null; | |
} | |
StringBuilder hex = new StringBuilder(5*bytes.length + 2); | |
hex.append("["); | |
if (bytes.length > 0) | |
{ | |
for (byte b : bytes ) { | |
hex.append("0x").append(HEXES[(b & 0xf0) >> 4]) | |
.append(HEXES[b & 0x0f]).append(","); | |
} | |
hex.deleteCharAt(hex.length()-1); | |
} | |
hex.append("]"); | |
return hex.toString(); | |
} | |
public static String byteToHexString(byte b) { | |
return String.format("0x%02X ", b); | |
} | |
/** | |
* Capitalizes the first character of the words in a string. | |
* | |
* @param s the input string | |
* @return a string with the first character of all words capitalized | |
*/ | |
public static String capitalize(String s) | |
{ | |
StringBuffer myStringBuffer = new StringBuffer(); | |
Pattern p = Pattern.compile("\\b(\\w)(\\w*)"); | |
Matcher m = p.matcher(s); | |
while (m.find()) { | |
if(!Character.isUpperCase(m.group().charAt(0))) | |
m.appendReplacement(myStringBuffer, m.group(1).toUpperCase()+"$2"); | |
} | |
return m.appendTail(myStringBuffer).toString(); | |
} | |
public static String capitalizeFully(String s) | |
{ | |
return capitalize(s.toLowerCase()); | |
} | |
public static String concat(Iterable<? extends CharSequence> strings, String delimiter) | |
{ | |
int capacity = 0; | |
int delimLength = delimiter.length(); | |
Iterator<? extends CharSequence> iter = strings.iterator(); | |
while (iter.hasNext()) { | |
CharSequence next = iter.next(); | |
if(!isNullOrEmpty(next)) | |
capacity += next.length() + delimLength; | |
} | |
StringBuilder buffer = new StringBuilder(capacity); | |
iter = strings.iterator(); | |
while (iter.hasNext()) { | |
CharSequence next = iter.next(); | |
if(!isNullOrEmpty(next)) { | |
buffer.append(next); | |
buffer.append(delimiter); | |
} | |
} | |
int lastIndexOfDelimiter = buffer.lastIndexOf(delimiter); | |
buffer.delete(lastIndexOfDelimiter, buffer.length()); | |
return buffer.toString(); | |
} | |
public static String concat(String first, String second) | |
{ | |
if(first == null) return second; | |
if(second == null) return first; | |
StringBuilder sb = new StringBuilder(first.length() + second.length()); | |
sb.append(first); | |
sb.append(second); | |
return sb.toString(); | |
} | |
public static String concat(String first, String... strings) | |
{ | |
StringBuilder sb; | |
if(first != null) sb = new StringBuilder(first); | |
else sb = new StringBuilder(); | |
for (String s: strings) { | |
if(!isNullOrEmpty(s)) | |
sb.append(s); | |
} | |
return sb.toString(); | |
} | |
public static <T extends CharSequence> String concat(T[] strings, String delimiter) | |
{ | |
int capacity = 0; | |
int delimLength = delimiter.length(); | |
for (T value : strings) { | |
if(!isNullOrEmpty(value)) | |
capacity += value.length() + delimLength; | |
} | |
StringBuilder buffer = new StringBuilder(capacity); | |
for (T value : strings) { | |
if(!isNullOrEmpty(value)) { | |
buffer.append(value); | |
buffer.append(delimiter); | |
} | |
} | |
int lastIndexOfDelimiter = buffer.lastIndexOf(delimiter); | |
buffer.delete(lastIndexOfDelimiter, buffer.length()); | |
return buffer.toString(); | |
} | |
/** | |
* Regular expression version of the String contains method. | |
* If used with a match from start or match from end regular expression, | |
* it becomes the regular expression version of the {@link String# | |
* startsWith(String prefix)} or {@link String#endsWith(String suffix)} | |
* methods. | |
* | |
* @param input the input string | |
* @param regex the regular expression to which this string is to be matched | |
* @return true if a match is found, otherwise false | |
*/ | |
public static boolean contains(String input, String regex) | |
{ | |
Pattern p = Pattern.compile(regex); | |
Matcher m = p.matcher(input); | |
if (m.find()) { | |
return true; | |
} | |
return false; | |
} | |
/** | |
* From www.javapractices.com EscapeChars.java | |
* | |
* @param url URL string to be encoded | |
* @return a encoded URL string | |
*/ | |
public static String encodeURL(String url) | |
{ | |
String result = null; | |
try { | |
result = URLEncoder.encode(url, "UTF-8"); | |
} | |
catch (UnsupportedEncodingException ex){ | |
throw new RuntimeException("UTF-8 not supported", ex); | |
} | |
return result; | |
} | |
/** | |
* Escapes HTML reserved characters and other characters which might cause Cross Site Scripting | |
* (XSS) hacks | |
* | |
* The following table comes from www.javapractice.com EscapeChars.java | |
* | |
* <P>The following characters are replaced with corresponding HTML character entities: | |
* | |
* <table border='1' cellpadding='3' cellspacing='0'> | |
* <tr><th> Character </th><th>Replacement</th></tr> | |
* <tr><td> < </td><td> < </td></tr> | |
* <tr><td> > </td><td> > </td></tr> | |
* <tr><td> & </td><td> & </td></tr> | |
* <tr><td> " </td><td> "</td></tr> | |
* <tr><td> \t </td><td> 	</td></tr> | |
* <tr><td> ! </td><td> !</td></tr> | |
* <tr><td> # </td><td> #</td></tr> | |
* <tr><td> $ </td><td> $</td></tr> | |
* <tr><td> % </td><td> %</td></tr> | |
* <tr><td> ' </td><td> '</td></tr> | |
* <tr><td> ( </td><td> (</td></tr> | |
* <tr><td> ) </td><td> )</td></tr> | |
* <tr><td> * </td><td> *</td></tr> | |
* <tr><td> + </td><td> + </td></tr> | |
* <tr><td> , </td><td> , </td></tr> | |
* <tr><td> - </td><td> - </td></tr> | |
* <tr><td> . </td><td> . </td></tr> | |
* <tr><td> / </td><td> / </td></tr> | |
* <tr><td> : </td><td> :</td></tr> | |
* <tr><td> ; </td><td> ;</td></tr> | |
* <tr><td> = </td><td> =</td></tr> | |
* <tr><td> ? </td><td> ?</td></tr> | |
* <tr><td> @ </td><td> @</td></tr> | |
* <tr><td> [ </td><td> [</td></tr> | |
* <tr><td> \ </td><td> \</td></tr> | |
* <tr><td> ] </td><td> ]</td></tr> | |
* <tr><td> ^ </td><td> ^</td></tr> | |
* <tr><td> _ </td><td> _</td></tr> | |
* <tr><td> ` </td><td> `</td></tr> | |
* <tr><td> { </td><td> {</td></tr> | |
* <tr><td> | </td><td> |</td></tr> | |
* <tr><td> } </td><td> }</td></tr> | |
* <tr><td> ~ </td><td> ~</td></tr> | |
* </table> | |
* | |
* @return a string with the specified characters replaced by HTML entities | |
*/ | |
public static String escapeHTML(String input) | |
{ | |
Iterator<Character> itr = stringIterator(input); | |
StringBuilder result = new StringBuilder(); | |
while (itr.hasNext()) | |
{ | |
Character c = itr.next(); | |
switch (c) | |
{ | |
case '<': | |
result.append("<"); | |
break; | |
case '>': | |
result.append(">"); | |
break; | |
case '&': | |
result.append("&"); | |
break; | |
case '"': | |
result.append("""); | |
break; | |
case '\t': | |
result.append("	"); | |
break; | |
case '!': | |
result.append("!"); | |
break; | |
case '#': | |
result.append("#"); | |
break; | |
case '$': | |
result.append("$"); | |
break; | |
case '%': | |
result.append("%"); | |
break; | |
case '\'': | |
result.append("'"); | |
break; | |
case '(': | |
result.append("("); | |
break; | |
case ')': | |
result.append(")"); | |
break; | |
case '*': | |
result.append("*"); | |
break; | |
case '+': | |
result.append("+"); | |
break; | |
case ',': | |
result.append(","); | |
break; | |
case '-': | |
result.append("-"); | |
break; | |
case '.': | |
result.append("."); | |
break; | |
case '/': | |
result.append("/"); | |
break; | |
case ':': | |
result.append(":"); | |
break; | |
case ';': | |
result.append(";"); | |
break; | |
case '=': | |
result.append("="); | |
break; | |
case '?': | |
result.append("?"); | |
break; | |
case '@': | |
result.append("@"); | |
break; | |
case '[': | |
result.append("["); | |
break; | |
case '\\': | |
result.append("\"); | |
break; | |
case ']': | |
result.append("]"); | |
break; | |
case '^': | |
result.append("^"); | |
break; | |
case '_': | |
result.append("_"); | |
break; | |
case '`': | |
result.append("`"); | |
break; | |
case '{': | |
result.append("{"); | |
break; | |
case '|': | |
result.append("|"); | |
break; | |
case '}': | |
result.append("}"); | |
break; | |
case '~': | |
result.append("~"); | |
break; | |
default: | |
result.append(c); | |
} | |
} | |
return result.toString(); | |
} | |
/** | |
* Replaces "&" with its entity "&" to make it a valid HTML link | |
* | |
* @param queryString a URL string with a query string attached | |
* @return a valid URL string to be used as a link | |
*/ | |
public static String escapeQueryStringAmp(String queryString) | |
{ | |
return queryString.replace("&", "&"); | |
} | |
public static String escapeRegex(String input) | |
{ | |
Iterator<Character> itr = stringIterator(input); | |
StringBuilder result = new StringBuilder(); | |
while (itr.hasNext()) | |
{ | |
Character c = itr.next(); | |
switch (c) | |
{ | |
case '.': | |
case '^': | |
case '$': | |
case '*': | |
case '+': | |
case '?': | |
case '(': | |
case ')': | |
case '[': | |
case '{': | |
result.append("\\").append(c); | |
break; | |
case '\\': | |
result.append("\\\\"); | |
break; | |
default: | |
result.append(c); | |
} | |
} | |
return result.toString(); | |
} | |
public static String escapeXML(String input) | |
{ | |
Iterator<Character> itr = stringIterator(input); | |
StringBuilder result = new StringBuilder(); | |
while (itr.hasNext()) | |
{ | |
Character c = itr.next(); | |
switch (c) | |
{ | |
case '"': | |
result.append("""); | |
break; | |
case '\'': | |
result.append("'"); | |
break; | |
case '<': | |
result.append("<"); | |
break; | |
case '>': | |
result.append(">"); | |
break; | |
case '&': | |
result.append("&"); | |
break; | |
default: | |
result.append(c); | |
} | |
} | |
return result.toString(); | |
} | |
public static String intToHexString(int value) { | |
StringBuilder buffer = new StringBuilder(10); | |
buffer.append("0x"); | |
buffer.append(HEXES[(value & 0x0000000F)]); | |
buffer.append(HEXES[(value & 0x000000F0) >>> 4]); | |
buffer.append(HEXES[(value & 0x00000F00) >>> 8]); | |
buffer.append(HEXES[(value & 0x0000F000) >>> 12]); | |
buffer.append(HEXES[(value & 0x000F0000) >>> 16]); | |
buffer.append(HEXES[(value & 0x00F00000) >>> 20]); | |
buffer.append(HEXES[(value & 0x0F000000) >>> 24]); | |
buffer.append(HEXES[(value & 0xF0000000) >>> 28]); | |
return buffer.toString(); | |
} | |
public static String intToHexStringMM(int value) { | |
StringBuilder buffer = new StringBuilder(10); | |
buffer.append("0x"); | |
buffer.append(HEXES[(value & 0xF0000000) >>> 28]); | |
buffer.append(HEXES[(value & 0x0F000000) >>> 24]); | |
buffer.append(HEXES[(value & 0x00F00000) >>> 20]); | |
buffer.append(HEXES[(value & 0x000F0000) >>> 16]); | |
buffer.append(HEXES[(value & 0x0000F000) >>> 12]); | |
buffer.append(HEXES[(value & 0x00000F00) >>> 8]); | |
buffer.append(HEXES[(value & 0x000000F0) >>> 4]); | |
buffer.append(HEXES[(value & 0x0000000F)]); | |
return buffer.toString(); | |
} | |
/** | |
* Checks if a string is null, empty, or consists only of white spaces | |
* | |
* @param str the input CharSequence to check | |
* @return true if the input string is null, empty, or contains only white | |
* spaces, otherwise false | |
*/ | |
public static boolean isNullOrEmpty(CharSequence str) | |
{ | |
return ((str == null) || (str.length() == 0)); | |
} | |
/** | |
* Formats TIFF long data field. | |
* | |
* @param data an array of int. | |
* @param unsigned true if the int value should be treated as unsigned, | |
* otherwise false | |
* @return a string representation of the int array. | |
*/ | |
public static String longArrayToString(int[] data, boolean unsigned) { | |
StringBuilder longs = new StringBuilder(); | |
longs.append("["); | |
for (int i=0; i<data.length; i++) | |
{ | |
if(unsigned) { | |
// Convert it to unsigned integer | |
longs.append(data[i]&0xffffffffL); | |
} else { | |
longs.append(data[i]); | |
} | |
longs.append(","); | |
} | |
longs.deleteCharAt(longs.length()-1); | |
longs.append("]"); | |
return longs.toString(); | |
} | |
public static boolean parseBoolean(String s) { | |
return Boolean.parseBoolean(s); | |
} | |
public static byte parseByte(String s) { | |
return Byte.parseByte(s); | |
} | |
public static byte parseByte(String s, int radix) { | |
return Byte.parseByte(s, radix); | |
} | |
public static double parseDouble(String s) { | |
return Double.parseDouble(s); | |
} | |
public static float parseFloat(String s) { | |
return Float.parseFloat(s); | |
} | |
public static int parseInt(String s) { | |
return Integer.parseInt(s); | |
} | |
public static int parseInt(String s, int radix) { | |
return Integer.parseInt(s, radix); | |
} | |
public static long parseLong(String s) { | |
return Long.parseLong(s); | |
} | |
public static long parseLong(String s, int radix) { | |
return Long.parseLong(s, radix); | |
} | |
public static short parseShort(String s) { | |
return Short.parseShort(s); | |
} | |
public static short parseShort(String s, int radix) { | |
return Short.parseShort(s, radix); | |
} | |
public static String quoteRegexReplacement(String replacement) | |
{ | |
return Matcher.quoteReplacement(replacement); | |
} | |
/** | |
* Formats TIFF rational data field. | |
* | |
* @param data an array of int. | |
* @param unsigned true if the int value should be treated as unsigned, | |
* otherwise false | |
* @return a string representation of the int array. | |
*/ | |
public static String rationalArrayToString(int[] data, boolean unsigned) | |
{ | |
if(data.length%2 != 0) | |
throw new IllegalArgumentException("Data length is odd number, expect even!"); | |
StringBuilder rational = new StringBuilder(); | |
rational.append("["); | |
for (int i=0; i<data.length; i+=2) | |
{ | |
long numerator = data[i], denominator = data[i+1]; | |
if (unsigned) { | |
// Converts it to unsigned integer | |
numerator = (data[i]&0xffffffffL); | |
denominator = (data[i+1]&0xffffffffL); | |
} | |
rational.append(numerator); | |
rational.append("/"); | |
rational.append(denominator); | |
rational.append(","); | |
} | |
rational.deleteCharAt(rational.length()-1); | |
rational.append("]"); | |
return rational.toString(); | |
} | |
/** | |
* Replaces the last occurrence of the string represented by the regular expression | |
* | |
* @param input input string | |
* @param regex the regular expression to which this string is to be matched | |
* @param replacement the string to be substituted for the match | |
* @return the resulting String | |
*/ | |
public static String replaceLast(String input, String regex, String replacement) | |
{ | |
return input.replaceAll(regex+"(?!.*"+regex+")", replacement); // Using negative look ahead | |
} | |
public static String reverse(String s) | |
{ | |
int i, len = s.length(); | |
StringBuilder dest = new StringBuilder(len); | |
for (i = (len - 1); i >= 0; i--) | |
dest.append(s.charAt(i)); | |
return dest.toString(); | |
} | |
public static String reverse(String str, String delimiter) | |
{ | |
if(isNullOrEmpty(delimiter)) { | |
return str; | |
} | |
StringBuilder sb = new StringBuilder(str.length()); | |
reverseIt(str, delimiter, sb); | |
return sb.toString(); | |
} | |
public static String reverse2(String str, String delimiter) | |
{ | |
if(isNullOrEmpty(delimiter) || isNullOrEmpty(str) || (str.trim().length() == 0) || (str.indexOf(delimiter) < 0)) { | |
return str; | |
} | |
String escaptedDelimiter = escapeRegex(delimiter); | |
// Keep the trailing white spaces by setting limit to -1 | |
String[] stringArray = str.split(escaptedDelimiter, -1); | |
StringBuilder sb = new StringBuilder(str.length() + delimiter.length()); | |
for (int i = stringArray.length-1; i >= 0; i--) | |
{ | |
sb.append(stringArray[i]).append(delimiter); | |
} | |
return sb.substring(0, sb.lastIndexOf(delimiter)); | |
} | |
private static void reverseIt(String str, String delimiter, StringBuilder sb) | |
{ | |
if(isNullOrEmpty(str) || (str.trim().length() == 0) || str.indexOf(delimiter) < 0) { | |
sb.append(str); | |
return; | |
} | |
// Recursion | |
reverseIt(str.substring(str.indexOf(delimiter)+delimiter.length()), delimiter, sb); | |
sb.append(delimiter); | |
sb.append(str.substring(0, str.indexOf(delimiter))); | |
} | |
public static String reverseWords(String s) | |
{ | |
String[] stringArray = s.split("\\b"); | |
StringBuilder sb = new StringBuilder(s.length()); | |
for (int i = stringArray.length-1; i >= 0; i--) | |
{ | |
sb.append(stringArray[i]); | |
} | |
return sb.toString(); | |
} | |
/** | |
* Formats TIFF short data field. | |
* | |
* @param data an array of short. | |
* @param unsigned true if the short value should be treated as unsigned, | |
* otherwise false | |
* @return a string representation of the short array. | |
*/ | |
public static String shortArrayToString(short[] data, boolean unsigned) | |
{ | |
StringBuilder shorts = new StringBuilder(); | |
shorts.append("["); | |
for (int i=0; i<data.length; i++) | |
{ | |
if(unsigned) { | |
// Convert it to unsigned short | |
shorts.append(data[i]&0xffff); | |
} else { | |
shorts.append(data[i]); | |
} | |
shorts.append(","); | |
} | |
shorts.deleteCharAt(shorts.length()-1); | |
shorts.append("]"); | |
return shorts.toString(); | |
} | |
public static String shortToHexString(short value) { | |
StringBuilder buffer = new StringBuilder(6); | |
buffer.append("0x"); | |
buffer.append(HEXES[(value & 0x000F)]); | |
buffer.append(HEXES[(value & 0x00F0) >>> 4]); | |
buffer.append(HEXES[(value & 0x0F00) >>> 8]); | |
buffer.append(HEXES[(value & 0xF000) >>> 12]); | |
return buffer.toString(); | |
} | |
public static String shortToHexStringMM(short value) { | |
StringBuilder buffer = new StringBuilder(6); | |
buffer.append("0x"); | |
buffer.append(HEXES[(value & 0xF000) >>> 12]); | |
buffer.append(HEXES[(value & 0x0F00) >>> 8]); | |
buffer.append(HEXES[(value & 0x00F0) >>> 4]); | |
buffer.append(HEXES[(value & 0x000F)]); | |
return buffer.toString(); | |
} | |
/** | |
* Converts stack trace to string | |
*/ | |
public static String stackTraceToString(Throwable e) { | |
StringWriter sw = new StringWriter(); | |
e.printStackTrace(new PrintWriter(sw)); | |
return sw.toString(); | |
} | |
/** | |
* A read-only String iterator from stackoverflow.com | |
* | |
* @param string input string to be iterated | |
* @return an iterator for the input string | |
*/ | |
public static Iterator<Character> stringIterator(final String string) | |
{ | |
// Ensure the error is found as soon as possible. | |
if (string == null) | |
throw new NullPointerException(); | |
return new Iterator<Character>() { | |
private int index = 0; | |
public boolean hasNext() { | |
return index < string.length(); | |
} | |
public Character next() { | |
/* | |
* Throw NoSuchElementException as defined by the Iterator contract, | |
* not IndexOutOfBoundsException. | |
*/ | |
if (!hasNext()) | |
throw new NoSuchElementException(); | |
return string.charAt(index++); | |
} | |
public void remove() { | |
throw new UnsupportedOperationException(); | |
} | |
}; | |
} | |
private StringUtils(){} // Prevents instantiation | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment