package de.jetwick.snacktory;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Util {
/**
* Reformat the timezone in a date string.
*
* @param str The input string
* @param signIdx The index position of the sign characters
* @return The reformatted string
*/
private static String reformatTimezone(String str, int signIdx) {
String str2 = str;
if (signIdx >= 0 &&
signIdx + 5 < str.length() &&
Character.isDigit(str.charAt(signIdx + 1)) &&
Character.isDigit(str.charAt(signIdx + 2)) &&
str.charAt(signIdx + 3) == ':' &&
Character.isDigit(str.charAt(signIdx + 4)) &&
Character.isDigit(str.charAt(signIdx + 5))) {
str2 = str.substring(0, signIdx + 3) + str.substring(signIdx + 4);
}
return str2;
}
// Empty checks
//-----------------------------------------------------------------------
/**
* <p>Checks if a String is empty ("") or null.</p>
*
* <pre>
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
* StringUtils.isEmpty(" ") = false
* StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false
* </pre>
*
* <p>NOTE: This method changed in Lang version 2.0.
* It no longer trims the String.
* That functionality is available in isBlank().</p>
*
* @param str the String to check, may be null
* @return <code>true</code> if the String is empty or null
*/
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
// IndexOf
//-----------------------------------------------------------------------
/**
* <p>Finds the first index within a String, handling <code>null</code>.
* This method uses {@link String#indexOf(int)}.</p>
*
* <p>A <code>null</code> or empty ("") String will return <code>INDEX_NOT_FOUND (-1)</code>.</p>
*
* <pre>
* StringUtils.indexOf(null, *) = -1
* StringUtils.indexOf("", *) = -1
* StringUtils.indexOf("aabaabaa", 'a') = 0
* StringUtils.indexOf("aabaabaa", 'b') = 2
* </pre>
*
* @param str the String to check, may be null
* @param searchChar the character to find
* @return the first index of the search character,
* -1 if no match or <code>null</code> string input
* @since 2.0
*/
public static int indexOf(String str, char searchChar) {
if (isEmpty(str)) {
return -1;
}
return str.indexOf(searchChar);
}
/**
* <p>Finds the first index within a String from a start position,
* handling <code>null</code>.
* This method uses {@link String#indexOf(int, int)}.</p>
*
* <p>A <code>null</code> or empty ("") String will return <code>(INDEX_NOT_FOUND) -1</code>.
* A negative start position is treated as zero.
* A start position greater than the string length returns <code>-1</code>.</p>
*
* <pre>
* StringUtils.indexOf(null, *, *) = -1
* StringUtils.indexOf("", *, *) = -1
* StringUtils.indexOf("aabaabaa", 'b', 0) = 2
* StringUtils.indexOf("aabaabaa", 'b', 3) = 5
* StringUtils.indexOf("aabaabaa", 'b', 9) = -1
* StringUtils.indexOf("aabaabaa", 'b', -1) = 2
* </pre>
*
* @param str the String to check, may be null
* @param searchChar the character to find
* @param startPos the start position, negative treated as zero
* @return the first index of the search character,
* -1 if no match or <code>null</code> string input
* @since 2.0
*/
public static int indexOf(String str, char searchChar, int startPos) {
if (isEmpty(str)) {
return -1;
}
return str.indexOf(searchChar, startPos);
}
/**
* <p>Finds the first index within a String, handling <code>null</code>.
* This method uses {@link String#indexOf(String)}.</p>
*
* <p>A <code>null</code> String will return <code>-1</code>.</p>
*
* <pre>
* StringUtils.indexOf(null, *) = -1
* StringUtils.indexOf(*, null) = -1
* StringUtils.indexOf("", "") = 0
* StringUtils.indexOf("", *) = -1 (except when * = "")
* StringUtils.indexOf("aabaabaa", "a") = 0
* StringUtils.indexOf("aabaabaa", "b") = 2
* StringUtils.indexOf("aabaabaa", "ab") = 1
* StringUtils.indexOf("aabaabaa", "") = 0
* </pre>
*
* @param str the String to check, may be null
* @param searchStr the String to find, may be null
* @return the first index of the search String,
* -1 if no match or <code>null</code> string input
* @since 2.0
*/
public static int indexOf(String str, String searchStr) {
if (str == null || searchStr == null) {
return -1;
}
return str.indexOf(searchStr);
}
/**
* Index of sign charaters (i.e. '+' or '-').
*
* @param str The string to search
* @param startPos The start position
* @return the index of the first sign character or -1 if not found
*/
private static int indexOfSignChars(String str, int startPos) {
int idx = indexOf(str, '+', startPos);
if (idx < 0) {
idx = indexOf(str, '-', startPos);
}
return idx;
}
/**
* <p>Parses a string representing a date by trying a variety of different parsers.</p>
*
* <p>The parse will try each parse pattern in turn.
* A parse is only deemed successful if it parses the whole of the input string.
* If no parse patterns match, a ParseException is thrown.</p>
* The parser parses strictly - it does not allow for dates such as "February 942, 1996".
*
* @param str the date to parse, not null
* @param parsePatterns the date format patterns to use, see SimpleDateFormat, not null
* @return the parsed date
* @throws IllegalArgumentException if the date string or pattern array is null
* @throws java.text.ParseException if none of the date patterns were suitable
* @since 2.5
*/
public static Date parseDateStrictly(String str, String[] parsePatterns) throws ParseException {
return parseDateWithLeniency(str, parsePatterns, false);
}
/**
* <p>Parses a string representing a date by trying a variety of different parsers.</p>
*
* <p>The parse will try each parse pattern in turn.
* A parse is only deemed successful if it parses the whole of the input string.
* If no parse patterns match, a ParseException is thrown.</p>
*
* @param str the date to parse, not null
* @param parsePatterns the date format patterns to use, see SimpleDateFormat, not null
* @param lenient Specify whether or not date/time parsing is to be lenient.
* @return the parsed date
* @throws IllegalArgumentException if the date string or pattern array is null
* @throws ParseException if none of the date patterns were suitable
*/
private static Date parseDateWithLeniency(String str, String[] parsePatterns,
boolean lenient) throws ParseException {
if (str == null || parsePatterns == null) {
throw new IllegalArgumentException("Date and Patterns must not be null");
}
SimpleDateFormat parser = new SimpleDateFormat();
parser.setLenient(lenient);
ParsePosition pos = new ParsePosition(0);
for (int i = 0; i < parsePatterns.length; i++) {
String pattern = parsePatterns[i];
// LANG-530 - need to make sure 'ZZ' output doesn't get passed to SimpleDateFormat
if (parsePatterns[i].endsWith("ZZ")) {
pattern = pattern.substring(0, pattern.length() - 1);
}
parser.applyPattern(pattern);
pos.setIndex(0);
String str2 = str;
// LANG-530 - need to make sure 'ZZ' output doesn't hit SimpleDateFormat as it will ParseException
if (parsePatterns[i].endsWith("ZZ")) {
int signIdx = indexOfSignChars(str2, 0);
while (signIdx >=0) {
str2 = reformatTimezone(str2, signIdx);
signIdx = indexOfSignChars(str2, ++signIdx);
}
}
Date date = parser.parse(str2, pos);
if (date != null && pos.getIndex() == str2.length()) {
return date;
}
}
throw new ParseException("Unable to parse the date: " + str, -1);
}
}