-1

I wish to turn a String looking like this:

String string = "5d3h6m";

Or even like this:

String string = " 44h 22d";

In any order, and with any number of spaces into an int symbolising the time in minutes.

(D=days H=Hours M=Minutes)

The problems I have had:

  1. Finding the characters in any order
  2. Getting any number of digits that appear before the letter

The following code is me trying to find a solution to the two problems (I am aware it is terrible code, that is why I am here, and no, I do not wish to be spoonfed):

if(timestring.contains(":")){
                            String[] timestringarray = timestring.split(":");
                            int timeinminutes = 0;
                            int timestringarraylength = timestringarray.length;
                            while(timestringarraylength>0){ 
                                if(timestringarray[timestringarraylength].matches("d{1}|D{1}")){
                                    timestring.replace("d{1}|D{1}","");
                                    long days = TimeUnit.MINUTES.convert(Integer.valueOf(timestring), TimeUnit.DAYS);
                                    int daysint = (int) (long) days;
                                    timeinminutes+=daysint;
                                }
                                if(timestringarray[timestringarraylength].matches("h{1}|H{1}")){
                                    timestring.replace("h{1}|H{1}","");
                                    long hours = TimeUnit.MINUTES.convert(Integer.valueOf(timestring), TimeUnit.HOURS);
                                    int hoursint = (int) (long) hours;
                                    timeinminutes+=hoursint;
                                }
                                if(timestringarray[timestringarraylength].matches("m{1}|M{1}")){
                                    timestring.replace("m{1}|M{1}","");
                                    long mins = TimeUnit.MINUTES.convert(Integer.valueOf(timestring), TimeUnit.MINUTES);
                                    int minsint = (int) (long) mins;
                                    timeinminutes+=minsint;
                                }
                                timestringarraylength--;
                            }
                            signConfig.set("Sign.time", Integer.valueOf(timeinminutes));
                        }

To specify, the String is a time entered by the user and won't change during the processing.
Thanks in advance.

  • 1
    Please, define `it doesn't even work...` and try to concentrate on one practical question. Questions like `how to implement this?` are rarely welcomed on stackoverflow – default locale Jul 23 '14 at 17:55
  • Also, this question might be useful: http://stackoverflow.com/questions/6403851/parsing-time-strings-like-1h-30min?rq=1 – default locale Jul 23 '14 at 17:58

1 Answers1

1

This should get you started

Given that it doesn't work isn't very helpful, this is about all you can hope for. Some direction on how to convert arbitrary encoded duration intervals into something you can process further.

This requires JDK 1.7+ because of the switch on String. Otherwise you will have to convert that to an if/elseif/else block.

Regular Expression (\d+)([hmsd]) explained.

import javax.annotation.Nonnull;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Q24917480
{
    public static void main(final String[] args)
    {
        final Pattern p = Pattern.compile("(\\d+)([hmsd])");
        final Matcher m = p.matcher("5d3h6m");
        long totalMillis = 0;
        while (m.find())
        {
            final int duration = Integer.parseInt(m.group(1));
            final TimeUnit interval = toTimeUnit(m.group(2));
            final long l = interval.toMillis(duration);
            totalMillis = totalMillis + l;
            System.out.format("TimeUnit.%s.toMillis(%s) = %d\n", interval.name(), duration, l);
        }
        System.out.println("TimeUnit.MILLISECONDS.toSeconds(totalMillis) = " + TimeUnit.MILLISECONDS.toSeconds(totalMillis));
        System.out.println("TimeUnit.MILLISECONDS.toMinutes(totalMillis) = " + TimeUnit.MILLISECONDS.toMinutes(totalMillis));
        System.out.println("TimeUnit.MILLISECONDS.toDays(totalMillis) = " + TimeUnit.MILLISECONDS.toDays(totalMillis));
    }

    public static TimeUnit toTimeUnit(@Nonnull final String c)
    {
        switch (c)
        {
            case "s": return TimeUnit.SECONDS;
            case "m": return TimeUnit.MINUTES;
            case "h": return TimeUnit.HOURS;
            case "d": return TimeUnit.DAYS;
            default: throw new IllegalArgumentException(String.format("%s is not a valid code [smhd]", c));
        }
    }
}

The expected output is:

TimeUnit.DAYS.toMillis(5) = 432000000
TimeUnit.HOURS.toMillis(3) = 10800000
TimeUnit.MINUTES.toMillis(6) = 360000
TimeUnit.MILLISECONDS.toSeconds(totalMillis) = 443160
TimeUnit.MILLISECONDS.toMinutes(totalMillis) = 7386
TimeUnit.MILLISECONDS.toDays(totalMillis) = 5
  • Great thanks for your help. I haven't thoroughly tested through using you method but I'm sure I will be able to extrapolate what I need from your example and customise for myself. –  Jul 23 '14 at 19:32
  • Also, I never meant to not be specific at all by saying "it doesn't work", I more like meant "I have tried for a very long time and can't get this to work, I probably don't know enough java to do this, could anybody help?" –  Jul 23 '14 at 19:33