Formatting hour in java 20h 10m 5000s to 20h 10m 10s - java

I am trying to create a small program that we give a wrong time for example: 20h 10m 5000s and that transforms it giving me back 20h 10m 50s. But I am unable to show you the code to see if you can help me, thank you very much :)
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.swing.JOptionPane;
public class EejercicioBasico3 {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat dateForm = new SimpleDateFormat("HH:mm:ss");
String UserDate = dateForm.format(JOptionPane.showInputDialog("Escriba una hora en formato hh-mm-ss"));
System.out.println(date);
System.out.println(UserDate);
}
}

Removing excess digits
I tend to understand from your question and comments that you are assuming that the user may type too many digits by mistake. I am further assuming that each number may be in the interval from 0 or 00 to 59, and any digits that make the number greater than 59 or wider than two digits are to be removed. It’s probably not perfect, but may get you started.
String inputTimeString = "20h 10m 5000s";
String outputTimeString
= inputTimeString.replaceAll("([6-9]|[0-5]\\d)\\d+", "$1");
System.out.println(outputTimeString);
Output is:
20h 10m 50s
The regular expression first matches either a digit in the range 6 – 9 or two digits starting with 0 through 5 to ensure that we got at most 59. This or these digits are captured as a group using round brackets around the group in the regexp. After the group any number of excess digits is matched. In the replacement string I use $1 to denote that the digits should be replaced with just what was matched in capturing group no. 1 (the only capturing group in this case).
Try another example:
String inputTimeString = "60h 010m 777s";
6h 01m 7s
Reservation: If this is a basic exercise from school, your teacher may have another solution in mind, but you can judge that better. If you haven’t learnt regular expressions, you probably should not hand in a solution that uses them. Maybe you were expected to iterate through the input string and add characters that are OK to a string buffer where you collect your output.
Converting excess seconds to minutes and hours
If instead you want excess seconds — over 59 seconds — converted to minutes and hours, use the Duration class:
String isoTimeString = "PT" + inputTimeString.replaceAll(" ", "");
Duration dur = Duration.parse(isoTimeString);
String outputTimeString = String.format("%dh %dm %ds",
dur.toHours(), dur.toMinutesPart(), dur.toSecondsPart());
System.out.println(outputTimeString);
21h 33m 20s
Duration.parse() requires ISO 8601 format. This is obtained from your format by prefixing PT (think period of time) and removing the spaces. The String.format() call reproduces your format.
Always avoid Date and SimpleDateFormat
The classes you were trying to use, SimpleDateFormat and Date, are poorly designed and long outdated and were never meant for a job like this. I recommmend that you never use them and always use java.time, the modern Java date and time API, for your time work. The Duration class is part of java.time.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601

In my opinion the bottom line would be...just don't accept an entry of: 20h 10m 5000s. Although the data is supplied through an Input Dialog window it can still be validated to contain the desired format (which is clearly shown as an example within the dialog) and if it isn't, inform the User to enter it again. Your code really shouldn't need to accommodate every typo and automatically correct it. It should however determine that there is a typo and inform the User to correct it or discard the input data altogether. Your application sets the rules, not the User (unfortunately however this may not be the case for everything). This may seem blunt but, you can't make everything idiot proof because tomorrow, there will just be a better idiot. Make the idiot do it right.
Determine your application's Time Entry rules:
Time is to be in three specific units: Hours, Minutes, and
Seconds.
Time is in 24 hour format meaning there is no such thing as AM or PM.
Each time unit (Hour, Minute, or Second) is to be comprised of two integer digits (ex: 15-32-05).
A separator character must be applied to separate each time
unit. The allowable character in this case is the Hyphen (-) or Minus character.
String userTime = "";
while (userTime.isEmpty()) {
userTime = JOptionPane.showInputDialog(null, "<html>Enter a time in "
+ "<font color=red><b>hh-mm-ss</b></font> format:<br><br></html>");
if (userTime == null) {
JOptionPane.showMessageDialog(null, "Time entry Canceled!", "Entry Canceled",
JOptionPane.WARNING_MESSAGE);
return;
}
if (!userTime.matches(
"^([0-1][0-9][-]|[2][0-3][-])([0-5][0-9][-])([0-5][0-9])$")) {
JOptionPane.showMessageDialog(null, "Invalid Time format supplied!",
"Invalid Entry", JOptionPane.WARNING_MESSAGE);
userTime = "";
}
}
String[] timeUnits = userTime.split("-");
String time = new StringBuilder("").append(timeUnits[0]).append("h ")
.append(timeUnits[1]).append("m ").append(timeUnits[2])
.append("s").toString();
JOptionPane.showMessageDialog(null, "<html>User supplied the time of:<br><br>"
+ "<center><font color=blue><b>" + time + "</b></font></center></html>",
"Invalid Entry", JOptionPane.INFORMATION_MESSAGE);
Obviously you don't need to do this sort of thing in a loop but you get the idea I'm sure.

Related

Receiving an error while executing method substring in Java

I have to do a String exercise where I have to enter a date like dd/mm/yyyy. Everything works fine except if I enter a space as the input, it prints this error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: begin 0, end 2, length 1
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3720)
at java.base/java.lang.String.substring(String.java:1909)
at ex5.main(ex5.java:17)
This is my code:
import cs1.*;
public class ex5
{
public static void main(String[] args)
{
String data = "18/08/2011";
//asking for the data
System.out.printf("DATA: ");
data = Keyboard.readString();
//system.out
System.out.printf("DIA: %s %n", data.substring(0, 2));
System.out.printf("MES: %s %n", data.substring(3, 5));
System.out.printf("ANY: %s", data.substring(6, 10));
}
}
My suggestion is that you test whether your input string has length 10. If it is shorter or longer, you know that it cannot have the expected format, so trying your substring calls will make no sense and may cause your program to crash as you have observed.
You need to call data.length(). This method will return the length of the string as an int, for example 10 for 18/08/2011 and 1 for a space. And you need to use an if statement to control that you only call substring() if the returned length is equal to 10. You will probably want an else part in which you issue a friendly message to the user about why your are not printing day, month and year.
This is a very good exercise as it may help you learn something we all have to learn: To validate, to check our input in order to determine whether it fulfils the requirements for the input and whether there is good reason to believe that it is wrong. The clear and strong recommendation is that you always do this.
Please realize that the user may enter any characters and any number of characters when your program asks for a date. Possible inputs include 18/8/2011 (one digit month and therefore too short), 18 d’agost de 2011 (too long) and any nonsense they can dream up. Make your program react as sensibly as possible in each case.
I would like to add that for production code one would use a DateTimeFormatter from the standard library for validating the input and parsing it into a date (a LocalDate).

Formatting time to remove unnecessary 00's from the timer

I'm trying to clean up my timer for my application but im having difficulties getting it to do what I want.
Would anyone know how to format H:M:S and remove the 00's?
Example the time may start like this: 12:34:56 (hh:mm:ss)
But once the time reaches lets say 00:34:56, remove the remaining 00's,
I'm a bit worried about performance which is why I'm here to find the more efficient way to format the time as this will be called a lot.
Would String.format("%02d:%02d", m, s).replaceAll("00:",""); be a wise choice?
Thanks.
Using a regular expression, you can delete only the first section '00:' using (It's only for deleting the hour part in a HH:MM::SS time format)
String.format("%02d:%02d", m, s).replaceAll("^00:","");
^ is a character to mark the beginning of a line
I assume you could be negligibly faster by just checking the first 2 characters:
if (timeString.charAt(0) == '0' && timeString.charAt(1) == '0')
timeString = timeString.substring(3);
I don't necessarily think that's great code, but 2 character checks would probably be faster than a larger string search. Not by much, though, so I doubt it's worth it.
(Made a fix based on the comment, changing == '1' to == '0' )
You have practically answered your own question. Just turn your thoughts into code.
What you need:
If the time is less than one hour, show only minutes and seconds; else, show hours, minutes and seconds.
Your code should read like the spoken version:
if (hours < 1) {
text = String.format("%02d:%02d", minutes, seconds);
} else {
text = String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
Simple, clean, fast, and easy for future programmers (including yourself, a year from now) to understand.

Parse any string to Sql date

I wonder if it's possible to parse any string (at least to try) to sql Date without specifing the string format? In other words I want to make a generic method who take as input a string and return an sql Date.
For instance I have:
String date1="31/12/2099";
String date2="31-12-2099";
and call parseToSqlDate(date1) and parseToSqlDate(date2) which will returns sql dates.
Short answer: No
Why: Parsing any string to a valid date is a task you as an intelligent being could not do (there is no "logical" way to determine the correct date), so you cannot "tell" a computer(program) to do that for you (see JGrice's comment, and there we still have 4-digit years).
Long answer: Maybe, if you are willed to either take risks or do not need a high rate of success.
How:
Define your minimal (format) requirements of a date. E.g. "a minimal date contains 1-8 numbers; 01/01/2001 , 01-01-01 , 01.01 (+current year) , 1.1 (+current year), 1 (+current month + current year) and/or "..contains 1-6 numbers and the letters for months"; 01-Jan-2001 and so on.
Split the input along any non-number/non-month-name characters, with a regex like [^0-9a-zA-Z] (quick thought, may hold some pitfalls)
You now have 1 to 3 (actually more if e.g. the time is included) separate numbers + 1 month name which can be aligned for year/month/day any way you like
For this "alignment", there are several possibilities:
Try a fixed format at first, if it "fits", take it, else try another (or fail)
(only of you get more than one entry at a time) guess the format by assuming all entries have the same (e.g. any number block containing values > 12 is not a month and > 31 is not a day)
BUT, and this is a big one, you can expect any such method to become a major PITA at some point, because you can never fully "trust" it to guess correctly (you can never be sure to have missed some special format or introduced some ambiguous interpretation). I outlined some cases/format, but definitely not all of them, so you will refine that method very often if you actually use it.
Appendix to your comment: "May be to add another parameter and in this way to know where goes day , month and so on?" So you are willed to add "pseudo-format-string" parameter specifying the order of day, month and year; that would make it a lot easier (as "simply" filtering out the delimiters can be achieved).

How to convert a string in java-format ddMMyyyyHmmss to a date by Oracle function to_date ()?

For example, there is a string line 0106201395810 (or 31052013155754), which fits the format of new SimpleDateFormat ("ddMMyyyyHmmss"), ie in the first case, 1 June 2013, 9 hours 58 minutes 10 seconds. Variant with to_date ('0106201395810 ',' DDMMYYYYHH24MISS ') is not suitable because it involves two characters in HH24.
You could try reassembling the string along these lines to have a zero in the right place- and use the DDMMYYYYHH24MISS format
to_date(
case length(input)
when 14 THEN -- the length is OK: this has 2 digits at the hour
input
when 13 THEN -- length is one short, have to add one '0'
substr(input,0,8) || '0' || substr(input, 9)
END,
'DDMMYYYYHH24MISS')
Though I must say, this is ugly, and probably has "less than optimal" performance... I'd much rather change the Java side format, as this format is clearly not a standard one. Individualism can be good at times - this is clearly not the case. This will just cause pain in the long term...
I am not quite sure about your specific need to use ddMMyyyyHmmss ; myself will be using HH for a 24hrs date format
Java
String s1 = "0106201395810";
Date d1 = (new SimpleDateFormat("ddMMyyyyHmmss")).parse(s1);
String s2 = (new SimpleDateFormat("ddMMyyyyHHmmss")).format(d1);
System.out.println("s2 "+s2);
SQL
select to_date ('01062013095810', 'DDMMYYYYHH24MISS' ) from dual

Getting JODA Duration to work

The following code does not print the days correctly, I need to print out days and minutes as well.
Duration duration = new Duration(1328223198241L - 1326308781131L);
Period p2 = new Period(duration.getMillis());
System.out.println(p2.getDays()); // prints 0, should print 22 days
System.out.println(p2.getHours()); // prints 531 which is expected.
According to the javadoc, "Only precise fields in the period type will be used. For the standard period type this is the time fields only. Thus the year, month, week and day fields will not be populated." thus you are getting zero.
Consider this alternative.
Duration duration = new Duration(1328223198241L - 1326308781131L);
Period p2 = new Period(duration.getMillis());
System.out.println(p2.getHours()); // prints 531 which is expected.
System.out.println(p2.toStandardDays().getDays()); // prints 22 days
This behavior is explained in the javadocs: "duration is larger than one day then all the remaining duration will be stored in the largest available precise field, hours in this case."
If you explain what you're trying to do, as opposed to how you're trying to do it, then I'm sure we'll be able to help out. For example, to find what I think you're trying to get from p2.getDays():
Days.daysBetween(dateTime1, dateTime2).getDays()
Does the following not suffice: System.out.println(duration.getStandardDays());

Categories