Convert String to appropriate DataType - java

I have a String that could be in many different formats. I need to be able to recognize the actual type of the value at runtime and then transform the value to that type.
For example. If I have a String Fri Feb 08 07:30:00 GMT 2013 this is actually a Date and a the String should be transformed into a date object and returned as such.
My current solution to this problem is to 'try' to convert it to a data type, if the conversion succeeds then all is good, if the conversion fails then move on to the next conversion attempt. This works, but is ugly and un-maintainable and I'm sure a better solution already exists out there.
Thanks.

You may use separate regular expression for each data type like this:
private final static Pattern DATE_PATTERN =
Pattern.compile (
"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) " +
"(?:Jan|Feb|Mar|Apr|May|June?|July?|Aug|Sept?|Oct|Nov|Dec) " +
"\\d\\d \\d\\d:\\d\\d:\\d\\d \\S+ \\d\\d\\d\\d");
private final static Pattern DOUBLE_PATTERN =
Pattern.compile (
"[\\+\\-]?\\d+\\.\\d+(?:[eE][\\+\\-]?\\d+)?");
private final static Pattern INTEGER_PATTERN =
Pattern.compile (
"[\\+\\-]?\\d+");
public static Object stringToObject (String string)
{
if (DATE_PATTERN.matcher (string).matches ())
return stringToDate (string);
else if (DOUBLE_PATTERN.matcher (string).matches ())
return Double.valueOf (string);
else if (INTEGER_PATTERN.matcher (string).matches ())
return Integer.valueOf (string);
else return string;
}

public static void main(String[] args) {
String s = "Fri Feb 08 07:30:00 GMT 2013";
SimpleDateFormat FT = new SimpleDateFormat("EEE MMM dd hh:mm:ss z yyyy");
Date d;
try {
d = FT.parse(s);
System.out.println(d);
} catch (ParseException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}

Try regular expression :
You can write a pattern for each data type you have, then match that pattern with each actual string you can associate a conversion for each match.
Here is a simple example (in pseudo Java):
String name = "Mike"; // This is an English name
String nameRegEx ="[A-Z][a-z]+"; //this patterns matches an english name
Matcher nameMatcher = new Matcher(regEx);
if (match.matches(name)){// I use the matches() method to verify the format of the string
Name nameObject = Converter.getNameObjectFromString(name);//I make the conversion
}
Checkout the java documentation for more details on matchers and regular expressions :
http://docs.oracle.com/javase/tutorial/essential/regex/

Your approach is fine, if the strings passed to you are out of your control. Just one more suggestion: You should apply every possible conversion and check for ambiguous strings. If multiple conversions succeed then the string is ambiguous and you should do some error handling, probably throwing an exception.

Related

reading a whole date and time with spaces in a file

this question may have been asked before but didn't find any clue for my problem here,
here is my problem : I have a file that is like this :
abc fg Sat Jan 08 19:06:21 IST 2022 4 4.0
here is my code that reads from the file :
BufferedReader read4 = new BufferedReader(new FileReader("shortDelvsFile.txt"));
while ((s = read4.readLine()) != null) {
token = new StringTokenizer(s);
double str1 = Double.parseDouble(token.nextToken());
Integer str2 = Integer.parseInt(token.nextToken());
while (token.hasMoreTokens()) {
System.out.println(convert(token.nextToken()));
}
ShortDeliveries d = new ShortDeliveries(token.nextToken(), token.nextToken(),
convert(token.nextToken()), str2, str1);
shortDelvss.add(d);
}
System.out.println("the short deliveries are : " + shortDelvss);
read4.close();
// this function is to convert the string to date
public static Date convert(String s) throws ParseException {
Date date = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy", Locale.ENGLISH).parse(s);
System.out.println(date);
return date;
}
now i want each ``token.nextToken();``` inside the ShortDeliveries to be like this:
token.nextToken() = fg
convert(token.nextToken()) = Sat Jan 08 19:06:21 IST 2022
str1 = 4
str2 = 4.0;```
the problem is that in convert(token.nextToken()) it doesn't take the whole date because tokenizer reads until the first space how can i fix that?
In case you know the date will always start with the day of week (e.g. Sat, Sun...), you can create a method to check if the current token is a known day.
In case this is a week day, collect the following 6 tokens (or whatever tokens count you need to form a valid date) and send them together as String to your convert method.
if (isDayOfWeek(token)) {
List<String> dateTokens = getNextTokens(token, 6);
String dateString = String.join(" ", dateTokens);
Date date = convert(dateString);
}
private boolean isDayOfWeek(String dayString) {
Locale locale = Locale.getDefault();
return Arrays.stream(DayOfWeek.values())
.map(day -> day.getDisplayName(TextStyle.SHORT, locale))
.anyMatch(dayString::equals);
}
private List<String> getNextTokens(StringTokenizer token, int tokenCount) {
return IntStream.rangeClosed(1, tokenCount)
.mapToObj(i ->token.nextToken())
.collect(Collectors.toList());
}
"s" is just a string that represents one line of your data
If you process it like a variable instead of a stream, you can use split.
There are several ways to do this, my preferences is as follows:
String parts_of_s = s.split(" ");
String s1 = s[0]; // you can in-line converting to double as you did above
String s2 = parts_of_s[1];
String remaining_string = s.substring(s1.length()+1 + s2.length()+1); // length indexes at zero
String string_date = remaining_string.substring(0, 28); // since you know how many characters there are in the format
String s3 = parts_of_s[8];
String s4 = parts_of_s[9];
If you're dealing with super-long lines of data where efficiency matters (you probably won't), you could pursue other avenues:
read the next 28 characters
read the next 6 tokens and concatenate with a space

regex to select after and upto specific character at same time

Is there any way I could select specific text after specific text and keep selecting until that word is selected. And once selected then leave the remaining.
Here is the example
ABCDEF
JHJHJNJN<098978686
<jjg>
HGHJFGV XXXX
10-10-2018
JHKGHKGHG
JKHJHHJM
10-10-2019 JGHHGHGVH
HBVJHBHBB
Just want to select this date 10-10-2018 in whole content which always comes after XXX with couple of spaces. I can't use just regex with specific value(10-10-2018) because date can be changed and possible that date pattern somewhere is also present like in example in last line.
Please share your thoughts..!
Thanks
Assuming the example is correct, then the following regex will extract just the date using find() and ensure that DOTALL is set.
"XXXX.*?[\\s]+([\\d]{1,2}-[\\d]{1,2}-[\\d]{4})"
Basically, search for XXX followed by spaces/newline then find the date. It will be placed into a group and can then be extracted.
You can see the operation at this location, though be sure to select "DOTALL".
public String getDate(String input)
{
String date = "";
Pattern dte = Pattern.compile("XXXX.*?[\\s]+([\\d]{1,2}-[\\d]{1,2}-[\\d]{4})", Pattern.DOTALL);
Matcher m = dte.matcher(input);
if (m.find() && m.groupCount() > 0) {
date = m.group(1);
}
return date;
}
Test case
#Test
public void testData() throws Exception
{
RegEx_52879334 re = new RegEx_52879334();
String input = re.getInputData();
String date = re.getDate(input);
assertEquals("10-10-2018", date);
System.out.println("Found: " + date);
}
Output:
Found: 10-10-2018

Validating the Date format using selenium Webdriver

I have a tab with name 'Preferences' where user can set the Date format in any format like DD/MM/YYYY, DD.MM.YYYY, MM/DD/YYYY etc and is applicable through out the web application
I have chosen a Date format DD.MM.YYYY and saved it
Now I need to validate a text field some where in my application where I give input say 01012001 and it should automatically take the input and convert to the preferred Date format 01.01.2001 where I have been saved in 'Preferences' tab
Could any one help me out how can I validate this in java?
In your case What I understand is you need to write function which will return you formatted date according to selected format.Below function will do the work and return you formatted string.
public String parseDate(StringBuilder dateString, String formatString) {
String separator = "";
String slashSeperator = "/";
if (formatString.contains(slashSeperator)) {
separator = slashSeperator;
} else {
String dotSeparator = ".";
if (formatString.contains(dotSeparator)) {
separator = dotSeparator;
}
}
if (dateString.length() == 8) {
dateString.insert(2, separator);
dateString.insert(5, separator);
} else {
return "False Date Entered";
}
return dateString.toString();
}
If you are using Java 8 you can check new Date library and its DateTimeFormatter. Use this formatter to parse date using Date.parse. Examples are included within docs.

Apply a date pattern a piece os expression

I have an expression working inside a Report (jasperReport), the language to work with expressions i groovy. the expression is
= Util.textoComun("OCURRENCIA")+ " "+Util.aFecha($F{fecha}).
Everything in the same box, but i just want to apply a date pattern at the second part of expression (Util.aFecha(xx)), is this possible?
I don't wanna to separate in two boxes.
Util is a java class.
afecha does:
public static Date aFecha(String s)
{
try
{
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
formatter.setLenient(false);
return formatter.parse(s);
} catch (Exception ex) {
System.out.println("Error convertint la data: " + ex);
}
return null;
}
Right, so from the edit, it appears that $F{fecha} is returning you a String which you parse into a Date with Util.aFecha. In that case (and assuming this is Groovy), you should be able to do:
Util.textoComun("OCURRENCIA")+ " "+Util.aFecha($F{fecha}).format( 'EEE, d MMM yyyy' )

How to delete all the characters after one character in the String?

I have a String which contains a date, for example "01-01-2012", then an space and then the time "01:01:01". The complete string is: "01-01-2012 01:01:01"
I would like to extract only the date from this string so at the end I would have "01-01-2012" but don't know how to do this.
Four options (last two added to make this one answer include the options given by others):
Parse the whole thing as a date/time and then just take the date part (Joda Time or SimpleDateFormat)
Find the first space using indexOf and get the leading substring using substring:
int spaceIndex = text.indexOf(" ");
if (spaceIndex != -1)
{
text = text.substring(0, spaceIndex);
}
Trust that it's valid in the specified format, and that the first space will always be at index 10:
text = text.substring(0, 10);
Split the string by spaces and then take the first result (seems needlessly inefficient to me, but it'll work...)
text = text.split(" ")[0];
You should consider what you want to happen if there isn't a space, too. Does that mean the data was invalid to start with? Should you just continue with the whole string? It will depend on your situation.
Personally I would probably go with the first option - do you really want to parse "01-01-2012 wibble-wobble bad data" as if it were a valid date/time?
String input = "01-01-2012 01:01:01";
String date = d.split(" ")[0];
Try this:
String date = s.substring(0, s.indexOf(" "));
Or even (because the length is fixed):
String date = s.substring(0, 10);
Or use StringUtils.substringBefore():
String date = StringUtils.substringBefore(s, " ");
Lots of ways to do this, a very simple method is to split the String at the space and use the first part (which will be the date):
String dateTime = "01-01-2012 01:01:01";
String date = dateTime.split(" ")[0];
You can use String.split() and take only the relevant String in your resultng String[] [in your example, it will be myString.split(" ")[0]
In that case where only one space is in the string, you can use String.split(" "). But this is a bad practice. You should parse the date with a DateFormat
.
You can use substring to extract the date only:
String thedatetime = "01-01-2012 01:01:01";
String thedateonly = thedate.substring(0, 10);
You should really read through the javadoc for String so you are aware of the available functions.
If you know in advance this is the format of the string, I'd do this:
public String getDateOnly(String fullDate){
String[] spl = fullDate.split(" ");
return spl[0];
}
You can do it either using string manipulation API:
String datetime = "01-01-2012 01:01:01";
int spacePos = datetime.indexOf(" ");
if (spacePos > 0) {
String date = datetime.substring(0, spacePos - 1);
}
or using regular expression:
Pattern p = Pattern.compile("(\\d{2}-\\d{2}-\\d{4})");
String datetime = "01-01-2012 01:01:01";
Matcher m = p.matcher(datetime);
if(m.find()) {
String date = m.group(1);
}
or using SimpleDateFormat
DateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date date = fmt.parse(datetime);
Calendar c = Calendar.getInstance();
c.setTime(date);
String date = c.getDayOfMonth() + "-" + c.getMonth() + "-" + c.getYear();
Use String.substring(int, int). If you are interested in the value of the date and time, then use SimpleDateFormatter to parse your string.
myString.substring(0,10);
If your string is always in that format (2 digits, minus, 2 digits, minus, 4 digits, space etc...) then you can use substring(int beginIndex, int endIndex) method of string to get what you want.
Note that second parameter is the index of character after returning substring.
If you want to explode the complete date from the string use this method.
/**
* #param dateTime format string
* #param type type of return value : "date" or "time"
* #return String value
*/
private String getFullDate(String dateTime, String type) {
String[] array = dateTime.split(" ");
if (type == "time") {
System.out.println("getDate: TIME: " + array[1]);
return array[1];
} else if (type == "date") {
System.out.println("getDate: DATE: " + array[0]);
return array[0];
} else {
System.out.println("NULL.");
return null;
}
}
Otherwise if you want only the date for explample 01-01-2012
use this:
/**
* #param datetime format string
* #return
*/
private String getOnlyDate(String datetime) {
String array[] = datetime.split("-");
System.out.println("getDate: DATE: " + array[0]);
return array[0];
}
I hope my answer will help you.

Categories