1

I am getting confused while parsing a time difference[which I receive from a webpage].

For Example : I get a string like this : 2 years 10 weeks 3 days 6 hours 7 min ago. Please note that the trailing s in year, week, day and hour may not be there in case of unity and not present in the min.

Currently, I want to get the difference stored like that and get the actual date and time[by subtracting from the current time?].

And, I am confused what to do? I know about the Time parsing methods but its not a regular time, Plus there's that trailing s!!!

Can anyone suggest a good approach to this?

Writwick
  • 2,133
  • 6
  • 23
  • 54
  • can you give an example of what you want? possibly a code attempt and where you're not sure to continue? – Eluvatar Jul 08 '13 at 17:46
  • `split` the string on spaces and take every other element. – Lee Meador Jul 08 '13 at 17:48
  • @Eluvatar I understand that. But I am totally confused. Don't know where to start to get the difference like this. Since, I used to parse time not difference, so thats why... – Writwick Jul 08 '13 at 17:49
  • @LeeMeador Will that be the best choice? – Writwick Jul 08 '13 at 17:49
  • are you sure you will always have spaces between things? If so, you can use String.split() to put all the different elements into different elements in an array, then go through them to determine which units are named; it appears from your example that there is always an integer in the position before those, so "parsing" is easy. You can test for "week" and "weeks". I don't see what the problem is... – arcy Jul 08 '13 at 17:50
  • Just test for `indexOfIgnoreCase("week")` which will ignore the 's'. A week is 7 * 24 * 60 * 60 seconds so add that into the variable collecting elapsed time. (I assume you don't care that the daylight savings week has either one less or one more hour in it.) – Lee Meador Jul 08 '13 at 17:52
  • Don't forget that it doesn't have to be the 'best' choice. It just has to be good enough. – Lee Meador Jul 08 '13 at 17:54
  • @LeeMeador I only thought that there were some in built way to do that. Anyways thanks. – Writwick Jul 08 '13 at 18:22
  • Can you confirm that when you have a zero minute for example, you still have somethign like "2 weeks 3 hours 0 min ago" ? – David Hofmann Jul 08 '13 at 19:18
  • No. Zero is never there and also sometimes some of the tokens are absent too. Okay I will try the codes later today. :) – Writwick Jul 09 '13 at 01:02

3 Answers3

0

I'd recomend calculating how much time the difference is in milliseconds then subtracting that from now, that would be simple however you will run into an issue with leap years.

Calendar cal = Calendar.getInstance();
cal.add(Calendar.YEAR, -2);
cal.add(Calendar.WEEK_OF_YEAR, -10);
cal.add(Calendar.DAY_OF_YEAR, -3);
cal.add(Calendar.HOUR_OF_DAY, -6);
cal.add(Calendar.MINUTE, -7);

that should work fine, but I haven't tested it. you're also going to have to handle cases where you don't get a value for weeks for example.

Eluvatar
  • 2,265
  • 19
  • 24
0

You can use this code. This takes in accoutn the ss and the possible absense of some tokens.

String orig = "2 years 10 weeks 3 days 6 hours 7 min ago";
String[] split = orig.replaceAll("[^0-9]+", " ").trim().split(" ");
Calendar cal = Calendar.getInstance();
int idx = 0;
if (orig.contains("yea")) cal.add(Calendar.YEAR, -Integer.parseInt(split[idx++]));
if (orig.contains("wee")) cal.add(Calendar.WEEK_OF_MONTH, -Integer.parseInt(split[idx++]));
if (orig.contains("day")) cal.add(Calendar.DATE, -Integer.parseInt(split[idx++]));
if (orig.contains("hour")) cal.add(Calendar.HOUR, -Integer.parseInt(split[idx++]));
if (orig.contains("min")) cal.add(Calendar.MINUTE, -Integer.parseInt(split[idx++]));

SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
String formattedString = sdf.format(cal.getTime());
System.out.println(formattedString); // it prints 04-26-2011 02:12:54
David Hofmann
  • 5,683
  • 12
  • 50
  • 78
  • that wont work. what if it's zero weeks (weeks would most likely be omitted) but 2 years, in this case years would get put into the weeks place. – Eluvatar Jul 08 '13 at 19:23
  • i'd use week_of_year instead of _of_month – njzk2 Jul 08 '13 at 20:50
  • @njzk2 can you explan what will the differene be ? Afaik the only difference will be when you get the value, but when you set the value it will behave the same with week_of_mohtn and week_of_year... – David Hofmann Jul 08 '13 at 21:01
  • I'm also unsure how it's reflected in adding. It looks like you have a few minor issues still, for day you're adding Calendar.DATE and for minute you're adding Calendar.HOUR again. – Eluvatar Jul 08 '13 at 21:36
  • DATE is for day, that is correct afaik, and I fix the last HOUR to minute, it didn't see it, thanks – David Hofmann Jul 08 '13 at 21:40
  • What's the difference between `WEEK_OF_MONTH` and `WEEK_OF_YEAR`? – Writwick Jul 09 '13 at 01:24
  • I think there's also a `sec` token sometimes. Anyways I will add it. BTW, I think I should use like : `YEAR`, `WEEK_OF_YEAR`, `DAY_OF_WEEK`, `HOUR_OF_DAY`, `MINUTE` and finally `SECOND`. – Writwick Jul 09 '13 at 05:55
  • @Writwick I think the difference comes when you get the hour or week, but when you set it does not make much difference. – David Hofmann Jul 09 '13 at 12:58
  • @DavidHofmann You don't have to mention that!!! :) Once I check it out I will accept it. Currently I have to write a lot of codes to put it into the working state... – Writwick Jul 09 '13 at 16:43
  • I think in place of `"[^0-9]+"`, I could use `"\\D+"` without any problem?? – Writwick Jul 11 '13 at 11:56
  • i think so, your pattern will check for ALL non digit unicode caracters, mine will check that the characters are not in the specified set, so I think mine might be faster. – David Hofmann Jul 11 '13 at 12:30
0

Using @Eluvatar's suggestion, assumg a space between each part:

Calendar cal = Calendar.getInstance();
String original = "2 years 10 weeks 3 days 6 hours 7 min ago";

// Split on whitespace separators ("\s+" means "one or more whitespace characters"),
// having trimmed whitespace at beginning and end.
String[] split = original.trim().split("\s+");

// Now parse each entry
int num = split.length;
int pos = 0;
while ((num-pos) >= 2) {
    if (split[pos].regionMatches(true, 0, "year", 0, 4)) {
          cal.add(Calendar.YEAR, -Integer.decode(split[++pos]));
    }
    else if (split[pos].regionMatches(true, 0, "month", 0, 5)) {
          cal.add(Calendar.MONTH, -Integer.decode(split[++pos]));
    }
    else if (split[pos].regionMatches(true, 0, "week", 0, 4)) {
          cal.add(Calendar.WEEK_OF_YEAR, -Integer.decode(split[++pos]));
    }
    // And so on through the other potential values, note that the last
    // number in regionMatches is the number of characters to match.

    pos++;
}

The "\s+" may need to become "\s+", see How do I split a string with any whitespace chars as delimiters?.

Community
  • 1
  • 1
Neil Townsend
  • 6,024
  • 5
  • 35
  • 52
  • There is no `month` keyword to be used. I just checked that out. I can change that according to my convenience though... :) – Writwick Jul 09 '13 at 01:27