Results 1 to 15 of 15
  1. #1
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default Times without dates.

    Am i missing something or is there a complete lack of support for String parsing of times without actual dates.

    I have tried Date formatter, Calendar, GraegorianCalendar objects and to no avail.

    The problem is such:
    System that periodically appends a short text message to a file, as part of the message there are various timestamps for the information. The time stamps are UTC timezone the actual date of the messages is found in the filename so filename-01122010. However we can assume that the program will only be reading todays file.

    Now I need to sort these time stamps and show them in order from the current time until some other predifined time.

    E.G.
    00:01:20 Current time, taken from system
    00:20:30 timestamp
    00:50:30 timestamp
    01:40:30 timestamp
    02:00:00 Final user defined time.

    Assume a 24hour clock and UTC timezone for above example

    My solution:
    Get String;
    Get Current Time;
    Tokenize String;
    Pass as ints to Calendar.set() methods
    Convert to longs from epoch through getTime() calls
    then order according to long values.

    I find it hard to believe that i have to write my own parser in order to convert the time to a usable date. Have i missed a package, or is there an open source package for time parsing. I have tried the following but the parse method gets the date wrong as well as the time.

    Java Code:
    private static final DateFormat timestampFormatter = new SimpleDateFormat("HH:mm:ss");
        static{
            timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        }
    Any opinions, comments and better approaches to problem welcome.

  2. #2
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default

    Quote Originally Posted by JavaJuJitZu View Post
    Now I need to sort these time stamps and show them in order from the current time until some other predifined time.

    E.G.
    00:01:20 Current time, taken from system
    00:20:30 timestamp
    00:50:30 timestamp
    01:40:30 timestamp
    02:00:00 Final user defined time.

    Timestamps in the form hh:mm:ss sorted lexographically (just as strings) will also be chronologically sorted. So why parse them at all?

  3. #3
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    Good point, however I have modified a JSlider to behave like a moving time ladder. Certain time stamps are of interest in predicted upcoming events. The sliders thumb has been modified so that it also shows a confidence interval for the prediction error. As the program is running the sliders minimum and maximum values are dynamically updated as the program runs. The timestamp however is held constant. The parsing is so i can have a numerical representation of times so i plug straight into the JSliders API methods.

  4. #4
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default

    Sorry, but I don't really understand the moving time ladder business. If, as you now say, you want a numerical representation of times, just use ints (seconds since midnight). Why use dates much less timezones?

  5. #5
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    Timezones is important as the application is for aeronautical industry and they use the UTC timezone as a global way of synchronization. I would like the numerical representation to preserve the date information.

    Java Code:
    Date date = new Date(), date.getTime() : long

    So far i have the following quick fix code to do what i want. Im just surprised there isn't a java native method to do what my code does.

    Java Code:
    private Date parseUTCtime(String s){
            StringTokenizer tokens = new StringTokenizer(s, ":");
            int hours = Integer.parseInt(tokens.nextToken());
            int minutes = Integer.parseInt(tokens.nextToken());
            int seconds = Integer.parseInt(tokens.nextToken());
            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
            cal.set(Calendar.HOUR_OF_DAY, hours);
            cal.set(Calendar.MINUTE, minutes);
            cal.set(Calendar.SECOND, seconds);
            return cal.getTime();
    
        }
    The time ladder window looks like this
    www dot imagegratis dot com/free/uploads/a0ee5c930a.jpg

    P.S. My post count is small so i can't link the image or post a proper link

  6. #6
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,185
    Rep Power
    20

    Default

    The only way you can preserve the date information is if you actually give the formatter a date to work with. You can't expect it to make assumptions.

    I would append the date (from the filename presumably) to the end of the time stamp you are currently converting to a Date, and also append UTC on after that as well, to give a format of "HH:mm:ss ddMMyyyy z".

  7. #7
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    You can't expect it to make assumptions.
    Your right there, I was thinking there was a way to specify to the formatter what date and timezone to expect. This would avoid having to modify the strings and adding string manipulation overhead to the program.

    DateFormatter has two methods setTimeZone and setCalendar, They appear to be equivalent from the testing i have done.

    I wrongly assumed that if i set the formatters Calendar to today in the UTC timezone it would parse the String "13:20:00" and produce a date object 7/1/2010 13:20:00 UTC. (Give that i have told the formatter what calendar i am working with)

    However it behaves as follows first it assumes the time is in my locales timezone, and assumes the date is the epoch so 1 Jan 1970. After that it forwards the time to the UTC timezone. So because i am GMT +10 the final date i end up with is
    23:20:00 1/1/1970 UTC. This result not only gets the date wrong but also the time. Only the timezone is now correct.

    My parsing method above will have to suffice. Thanks for the help.

  8. #8
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,185
    Rep Power
    20

    Default

    Those are to do with formatting, not parsing, at least in the main.

    As for overhead on String concatentation, it really isn't going to be much and I seriously doubt it will impact on your system in any noticeable way. In fact, it's almost certainly no slower than setting the date on a calendar. After all, all you're doing is concatenating 3 strings together. In fact, 2 each time (since I would hope you'd pre-concatenate the date and timezone stuff into a single string).

    Your current parsing method is significantly more complicated, and involves more work for the JVM. I mean, you're creating a Calendar each time!

  9. #9
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    Haha yes the method above was a rush job.

    I suppose you have a point, but i rather not read the date from the filename, as its not guaranteed to have the current date. Also i rather not put that constraint on the file as its generated by another system that i really have no say in its future development.

    So the question now is whats quicker:

    Java Code:
    Calender cal = new cal...
    public Date parseMethod(String s){
    tokenizestring;
    set Calendar;
    return cal.toDate();
    }
    or

    Java Code:
    formatter = new formatter;
    Calender cal = new Calender;
    final String dateToConCat = cal.getDate // slightly more involved here but we only do it once
    public Date parseMethod(String S){
    String  correctFormat = concate(s , dateToConCat);
    return formatter.parse(correctFormat);
    }

  10. #10
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,185
    Rep Power
    20

    Default

    Well, I'd say:

    Java Code:
    // Get todays date as a String, UTC
    String date = new SimpleDateFormat("ddMMyyyy z").format(Calendar.getInstance(Timezone.UTC).getTime);
    // Now do all my reading of files
    SimpleDateFormat sdf = new SimpleDateFormat("(see my previous post)");
    while (reading files) {
        ...
        Date dateTime = sdf.parse(entryDate + date);
        ...
    }
    I count 3 lines.

  11. #11
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    3 lines but lots of invocations.

    but the guts of it is which is faster, cal.todate or the formatters parse, having a quick look at the source

    cal.getTime uses the Date(long) constructor, calculating ms from epoch.

    formatter
    Java Code:
        public Date parse(String text, ParsePosition pos)
        {
        
            checkNegativeNumberExpression();
        
            int start = pos.index;
            int oldStart = start;
            int textLength = text.length();
    
            calendar.clear(); // Clears all the time fields
    
            boolean[] ambiguousYear = {false};
    
    
            for (int i = 0; i < compiledPattern.length; ) {
                int tag = compiledPattern[i] >>> 8;
    	    int count = compiledPattern[i++] & 0xff;
    	    if (count == 255) {
    		count = compiledPattern[i++] << 16;
    		count |= compiledPattern[i++];
    	    }
    
    	    switch (tag) {
    	    case TAG_QUOTE_ASCII_CHAR:
    		if (start >= textLength || text.charAt(start) != (char)count) {
    		    pos.index = oldStart;
    		    pos.errorIndex = start;
    		    return null;
    		}
    		start++;
    		break;
    
    	    case TAG_QUOTE_CHARS:
    		while (count-- > 0) {
    		    if (start >= textLength || text.charAt(start) != compiledPattern[i++]) {
    			pos.index = oldStart;
    			pos.errorIndex = start;
    			return null;
    		    }
    		    start++;
    		}
    		break;
    
    	    default:
    		// Peek the next pattern to determine if we need to
    		// obey the number of pattern letters for
    		// parsing. It's required when parsing contiguous
    		// digit text (e.g., "20010704") with a pattern which
    		// has no delimiters between fields, like "yyyyMMdd".
    		boolean obeyCount = false;
            
            
                    // In Arabic, a minus sign for a negative number is put after
                    // the number. Even in another locale, a minus sign can be
                    // put after a number using DateFormat.setNumberFormat().
                    // If both the minus sign and the field-delimiter are '-',
                    // subParse() needs to determine whether a '-' after a number
                    // in the given text is a delimiter or is a minus sign for the
                    // preceding number. We give subParse() a clue based on the
                    // information in compiledPattern.
                    boolean useFollowingMinusSignAsDelimiter = false;
            
            
                    if (i < compiledPattern.length) {
                        int nextTag = compiledPattern[i] >>> 8;
                        if (!(nextTag == TAG_QUOTE_ASCII_CHAR || nextTag == TAG_QUOTE_CHARS)) {
                            obeyCount = true;
                        }
                
                        if (hasFollowingMinusSign &&
                             (nextTag == TAG_QUOTE_ASCII_CHAR ||
                               nextTag == TAG_QUOTE_CHARS)) {
                            int c;
                            if (nextTag == TAG_QUOTE_ASCII_CHAR) {
                                 c = compiledPattern[i] & 0xff;
                            } else {
                                c = compiledPattern[i+1];
                            }
                    
                            if (c == minusSign) {
                                useFollowingMinusSignAsDelimiter = true;
                            }
                        }  
    		}
    		start = subParse(text, start, tag, count, obeyCount,
    				 ambiguousYear, pos, useFollowingMinusSignAsDelimiter);
    		if (start < 0) {
    		    pos.index = oldStart;
    		    return null;
    		}
    	    } 
                //end switch(tag)
    	}
            //end for()
    
            // At this point the fields of Calendar have been set.  Calendar
            // will fill in default values for missing fields when the time
            // is computed.
    
            pos.index = start;
    
            // This part is a problem:  When we call parsedDate.after, we compute the time.
            // Take the date April 3 2004 at 2:30 am.  When this is first set up, the year
            // will be wrong if we're parsing a 2-digit year pattern.  It will be 1904.
            // April 3 1904 is a Sunday (unlike 2004) so it is the DST onset day.  2:30 am
            // is therefore an "impossible" time, since the time goes from 1:59 to 3:00 am
            // on that day.  It is therefore parsed out to fields as 3:30 am.  Then we
            // add 100 years, and get April 3 2004 at 3:30 am.  Note that April 3 2004 is
            // a Saturday, so it can have a 2:30 am -- and it should. [LIU]
            /*
            Date parsedDate = calendar.getTime();
            if( ambiguousYear[0] && !parsedDate.after(defaultCenturyStart) ) {
                calendar.add(Calendar.YEAR, 100);
                parsedDate = calendar.getTime();
            }
            */
            // Because of the above condition, save off the fields in case we need to readjust.
            // The procedure we use here is not particularly efficient, but there is no other
            // way to do this given the API restrictions present in Calendar.  We minimize
            // inefficiency by only performing this computation when it might apply, that is,
            // when the two-digit year is equal to the start year, and thus might fall at the
            // front or the back of the default century.  This only works because we adjust
            // the year correctly to start with in other cases -- see subParse().
            Date parsedDate;
            try {
                if (ambiguousYear[0]) // If this is true then the two-digit year == the default start year
                {
                    // We need a copy of the fields, and we need to avoid triggering a call to
                    // complete(), which will recalculate the fields.  Since we can't access
                    // the fields[] array in Calendar, we clone the entire object.  This will
                    // stop working if Calendar.clone() is ever rewritten to call complete().
                    Calendar savedCalendar = (Calendar)calendar.clone();
                    parsedDate = calendar.getTime();
                    if (parsedDate.before(defaultCenturyStart))
                    {
                        // We can't use add here because that does a complete() first.
                        savedCalendar.set(Calendar.YEAR, defaultCenturyStartYear + 100);
                        parsedDate = savedCalendar.getTime();
                    }
                }
                else parsedDate = calendar.getTime();
            }
            // An IllegalArgumentException will be thrown by Calendar.getTime()
            // if any fields are out of range, e.g., MONTH == 17.
            catch (IllegalArgumentException e) {
                pos.errorIndex = start;
                pos.index = oldStart;
                return null;
            }
    
            return parsedDate;
        }
    I love the calendar.clear() call at the start there thnx java.

    Can we stick a solved on this we really are just entertaining ourselves here now :-)

    thnx all specially tolls for the help. Been good to bounce ideas around.

  12. #12
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    oh the formatter.parse(String s) calls the parse(string , pos ) not much to see in the first method.

  13. #13
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,185
    Rep Power
    20

    Default

    I just get the impression you're micro-optimising, which is one of the most pointless exercises in existence...:)

    The method I've mentioned is, as far as these things go, the "standard" for this sort of thing. As for getDate(), it's pretty irrelevant since it's called once. Prsing is what you're doing, so use the parser supplied...that's my position.

  14. #14
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    Agreed. Onto bigger things.

    [SOLVED]

  15. #15
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

Similar Threads

  1. My buttons all perform their action like 100 times
    By 711groove in forum New To Java
    Replies: 0
    Last Post: 12-13-2009, 11:49 AM
  2. Difference in seconds between two times
    By jazzy639 in forum New To Java
    Replies: 11
    Last Post: 09-26-2009, 07:58 PM
  3. Replies: 8
    Last Post: 06-07-2009, 03:29 AM
  4. Playing an AudioInputStream multiple times
    By pmgallardo in forum Advanced Java
    Replies: 6
    Last Post: 03-09-2009, 05:29 PM
  5. Replies: 3
    Last Post: 10-02-2008, 06:48 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •