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
Related
I have an input GEDCOM file with tons of individual/family records. The purpose is to format their data into this form:
name(p6, 'Harry Buis').
birth(p6, date(1927,11,17)).
death(p6, date(2001,08,21)).
famc(p6, f3).
fams(p6, f2).
I have been able to pull out the person number and their name and print it to an output file, however I am having trouble parsing the birth/death dates. I want to be able to use substring to assign the birthDay, birthMonth, and BirthYear as Integers so I can print it to the output file. It must be Integers so I can sort by date. Here is a sample of one client's data from the input file.
0 #P6# INDI
1 BIRT
2 DATE 17 Nov 1924
1 NAME Harry /Buis/
1 DEAT Age: 76
2 DATE 21 Aug 2001
1 SEX M
1 FAMC #F3#
1 FAMS #F2#
And here is my source code of what I have so far:
public class Main {
static Scanner scan;
static BufferedWriter outFile;
static int birthYear = 0;
static int birthMonth = 0;
static String birthDay = "";
static int deathYear = 0;
static int deathMonth = 0;
static int deathDay = 0;
static String name = "";
static String person = "";
static String sex = "";
static String famC = "";
static String famS = "";
static String man = "";
static String woman = "";
static String child = "";
public static void parse() throws IOException {
scan = new Scanner(new FileReader("pbuis.ged"));
outFile = new BufferedWriter(new FileWriter("output.txt"));
String reader = scan.nextLine();
int count = 0;
while (scan.hasNextLine()) {
if (reader.contains("NAME") && count < 1) {
reader = reader.substring(1).replace("/", "");
count++;
System.out.println(reader);
name = reader.replace("NAME", "");
}
if (reader.startsWith("0")) {
person = reader.trim().substring(2, 7).replace("#", "")
.replace("I", "").trim().toLowerCase();
System.out.print(person);
count = 0;
}
if (reader.contains("BIRT")) {
scan.nextLine();
birthDay = Integerreader.substring(6, 9).trim();
}
if (reader.equalsIgnoreCase("") || reader.equalsIgnoreCase(" ")) {
outFile.write("name(" + person + ", " + "'" + name.trim() + "'"
+ ")." + "\n" + birthDay);
}
reader = scan.nextLine();
}
}
public static void main(String[] args) throws IOException {
parse();
}
}
Without the if statement (contains "BIRT"), and "birthDay" not in the outFile.write() method, my output looks like this:
name(p1, 'Paul Edward Buis').
name(p2, 'Thomas Edward Buis').
name(p3, 'Jennifer Joy Buis').
name(p4, 'Daniel Paul Buis').
name(p5, 'Barbara Joy VanderWall').
name(p6, 'Harry Buis').
which is a good start.
But when I have that if statement, I get an error like this, and nothing prints:
p1Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 9
at java.lang.String.substring(Unknown Source)
at Main.parse(Main.java:50)
at Main.main(Main.java:64)
Now, I have tried every combination of substringing index values, and nothing seems to work. Any idea on how I fix this?
Thanks in advance.
I suggest you use a Date function. Date functions can be sorted easier than year/month/date. If you really want, store them as the milliseconds since the epoch.
To parse the date, use a SimpleDateFormatter. I believe something like this would work:
SimpleDateFormatter dateFormat=new SimpleDateFormat("dd mmm yyyy")
Date birth=date.parse("17 jul 1984",0);
One you get it in to the Date format, you can do a lot of neat things, like these:
Date date1, date2;
date1.after(date2);
date1.compareTo(date2)
You could even get the minutes or seconds, but I don't recommend that. Note the 0 refers to the index starting the string, so you could just specify the index where the format starts, and you're good. Overall, I think this is a lot cleaner.
Date parsing from GEDCOM files is tricky. You can use a SimpleDateFormatter for any dates that are in dd MMM yyyy format (like 26 SEP 2015) but GEDCOM supports a lot of weird variations, including imprecise dates where you only have the month and year, or just the year. It also allows prefixes like "ABT" to indicate that something occurred around a specific date, allows for ranges ("BET date1 AND date2") and ("FROM date1 TO date2"), and a lot of other complex behavior (French Republican or Hebrew calendars, anyone?)
I would recommend using gedcom4j (http://gedcom4j.org), which is a java library you can link into your program to load your data into Java objects and then do what you need. The DateParser class in that library can interpret your string values and turn them into java.util.Date values so you can do what you're describing.
What I'm trying to do:
I'm trying to convert a 4-digit military time into the standard 12 hour time format, with a colon and an added PM or AM without the use of importing anything before my code (I'm making a method that requires nothing other than java 101 techniques).
My situation:
I have milTime, which I manually change around for now every time I run it(as declared up top, currently at 1100), until I convert it into a method and submit the assignment, in which it will take in milTime, and will return milTimeString for the main program to print. I'm currently using BlueJ as an IDE, (I'm not sure if that's the best one to use?)
Example of input and output:
If 0056 were given, I would have to return 12:56am.
If 1125 were given, I would have to return 11:25am.
If 2359 were given, I would have to return 11:59pm.
Issues I need help with
When I execute, my am / pm boolean fails somewhere and it always outputs pm, no matter if I input 11:24 or 23:24.
It's probably obvious I'm working too hard to generate the output, but I don't know an easier way (Other than importing something to do it for me, which I don't want to do).
I humbly submit to any criticism on my bloated current code, and any corrections in my long-winded request. I've looked around for alternate answers, and everything involved importing or knowledge beyond me. Thanks for your time so far, and thanks in advance everyone.
public class timeTest
{
public static void main(String []args)
{
/*Declare my variables*/
int milTime = 2400;
String timeString = "";
boolean pm;
/*determine AM or PM and convert over 1200 into a clock's digits */
if (milTime >1259)
{
if (milTime <1200)
{
pm = false;
}
else
{
pm = true;
}
milTime = (milTime - 1200);
}
else
{
}
/*figure out my digits*/
int fourthDigit = milTime%10;
milTime = milTime/10;
int thirdDigit = milTime%10;
milTime = milTime/10;
int secondDigit = milTime%10;
milTime = milTime/10;
int firstDigit = milTime%10;
/*build each side of the colon*/
String hoursString = thirdDigit + "" + fourthDigit;
String minutesString = firstDigit + "" + secondDigit;
/*determine if the first digit is zero and if so, omit it*/
if (firstDigit == 0 )
{
minutesString = "" + secondDigit;
}
else
{
}
if (secondDigit == 0)
{
minutesString = "12";
}
else
{
}
/*build the total string and return the result with AM or PM based on conditional boolean.*/
if (pm = true)
{
timeString = (minutesString + ':' + hoursString + "pm");
}
else
{
}
if (pm = false)
{
timeString = (minutesString + ':' + hoursString + "am");
}
else
{
}
System.out.println(timeString);
}
}
Your problem is screaming out that you should be using your own custom data formatter. I like using the Joda Time library and its DateTime class instead of the built-in Java Date and Calendar classes. Therefore, instead of SimpleDateFormat, I recommend that you use a DateTimeFormat to create a DateTimeFormatter, which you will then use to convert your String into a DateTime. You will need one DateTimeFormatter for each of input and output. For example:
String rawTimestamp = "2300"; // For example
DateTimeFormatter inputFormatter = DateTimeFormat.forPattern("HHmm");
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("hh:mm a");
DateTime dateTime = inputFormatter.parseDateTime(rawTimestamp);
String formattedTimestamp = outputFormatter.print(dateTime.getMillis());
return formattedTimestamp;
Try this out!
You can do this much, much simpler, using a clever string conversion and SimpleDateFormat, here is the example but parsed in two lines:
// Heres your military time int like in your code sample
int milTime = 56;
// Convert the int to a string ensuring its 4 characters wide, parse as a date
Date date = new SimpleDateFormat("hhmm").parse(String.format("%04d", milTime));
// Set format: print the hours and minutes of the date, with AM or PM at the end
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a");
// Print the date!
System.out.println(sdf.format(date));
// Output: 12:56 AM
if (pm = true)
if (pm = false)
A single equal sign is an assignment. You want to do a comparison:
if (pm == true)
if (pm == false)
These could also be written more idiomatically as:
if (pm)
if (!pm)
That's the main problem. Another is your logic for setting pm. You only need a single if statement, with the line subtracting 1200 placed inside the pm = true block.
if (milTime < 1200)
{
pm = false;
}
else
{
pm = true;
milTime -= 1200;
}
There are a few other bugs that I'll leave to you. I trust these corrections will get you a bit further, at least.
public static String convert24HourToAmPm(String time) {
if (time == null)
return time;
// Convert time where time is like: 0100, 0200, 0300....2300...
if (time.length() == 4 && Helper.isInteger(time)) {
String hour = time.substring(0,2);
String minutes = time.substring(2,4);
String meridian = "am";
if (hour.substring(0,2).equals("00")) {
hour = "12";
} else if (hour.substring(0,1).equals("1") || hour.substring(0,1).equals("2")) {
meridian = "pm";
Integer militaryHour = Integer.parseInt(hour);
Integer convertedHour = null;
if (militaryHour > 12) {
convertedHour = (militaryHour - 12);
if (convertedHour < 10)
hour = "0" + String.valueOf(convertedHour);
else
hour = String.valueOf(convertedHour);
}
}
time = hour + ":" + minutes + " " + meridian;
}
// TODO - Convert time where time is like 01:00...23:00...
return time;
}
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.
I hava one string "2013-1-31 08:25 PM"
i want to split from space and :
i able to split after space it become "2013-1-31 08" and "25 PM"
now i want the "2013-1-31" and "08"
i dont not able to get the value in the 08 in the new string but i get the "2013-1-31"
String view_datee = view_date.getText().toString();
String[] separated = view_datee.split(":");
String first =separated[0];
String second=separated[1];
String[] newSeperated = first.split(" ");
String third = newSeperated[0];
String four= newSeperated[1];
Log.i("first",first);
Log.i("second",second);
Log.i("third", third);
Log.i("four", four);
I do not how to get the four value means 08 .
Here is an example using a date / calendar (it uses desktop java but easily transposable):
public static void main(String args[]) throws Exception {
String data = "2013-1-31 08:25 PM";
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd hh:mm a");
Calendar cal = Calendar.getInstance();
cal.setTime(fmt.parse(data));
//2013-1-31
System.out.println(new SimpleDateFormat("yyyy-M-dd").format(cal.getTime()));
//20
System.out.println(cal.get(Calendar.HOUR_OF_DAY));
//08
System.out.println(new SimpleDateFormat("hh").format(cal.getTime()));
}
Note that 08:25 PM is 20:05 so you can get either 08 or 20 depending on what you need. I showed both in my example.
Try this,
public static void main(String[] args) {
String str = "2013-1-31 08:25 PM";
System.out.println("[Date:"+str.split(" ")[0]+"][Hours:"+str.split(":")[0].split(" ")[1]+"]");
}
Output,
run:
[Date:2013-1-31][Hours:08]
BUILD SUCCESSFUL (total time: 1 second)
From the official Javadoc, split takes a RegExp as argument.
So, you cannot use " " as split argument.
Instead, you should use "\s" to sepparate the string by whitespace.
Then, your code would be:
String[] separated = view_datee.split(":");
String first =separated[0];
String second=separated[1];
String[] newSeperated = first.split("\\s");
String third = newSeperated[0];
String four= newSeperated[1];
Log.i("first",first);
Log.i("second",second);
Log.i("third", third);
Log.i("four", four);
Are u sure String ends with PM Or AM
Then u can do like this
String s= "2013-1-31 08:25 PM";
String newStr=s.substring(s.indexOf(" ")+1,s.lastIndexOf(" "));
System.out.println(newStr);
String result[]=newStr.split(":");
System.out.println(result[0]);
System.out.println(result[1]);
check below code, its working properly
String date = "2013-1-31 08:25 PM";
String[] split = date.split(":");
System.out.println(split[0]+"date:::" + split[1] );
String[] Datesplit = split[0].split(" ");
System.out.println(Datesplit[0]+"date splited:::" + Datesplit[1] );
Output below
2013-1-31 08date:::25 PM
2013-1-31date splited:::08
I have checked out your code and its working properly..
Here is i am posting whatever i have typed and excuted:
String teststr = "2013-1-31 08:25 PM";
System.out.println("teststr: " + teststr);
String[] separated = teststr.split(":");
String first = separated[0];
String second = separated[1];
String[] newSeperated = first.split(" ");
String third = newSeperated[0];
String four = newSeperated[1];
System.out.println("first : "+first);
System.out.println("second : "+second);
System.out.println("third : "+third);
System.out.println("fourth : "+four);
and its giving me following output:
teststr: 2013-1-31 08:25 PM
first : 2013-1-31 08
second : 25 PM
third : 2013-1-31
fourth : 08
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.