I have a String that represents a time value and is stored in the following format:
1:31:25
I would like to replace the colons and change the format to:
1h 31m 25s
What function in Java will let me replace the first two colons with 'h ' and 'm ', and the end of the string with 's'.
You could do something like this:
String[] s = myString.split(":");
String.format("%sh %sm %ss", s);
Or even compact!
String.format("%sh %sm %ss", myString.split(":"));
String time = "1:31:25";
String formattedTime = time.replaceFirst(":","h ").replaceFirst(":","m ").concat("s");
String input = "1:31:25";
String[] tokens = input.split(":");
String output = tokens[0] + "h " + tokens[1] + "m " + tokens[2] + "s";
Repeated use of the String.replaceFirst() method would help you here.
Simply replace your first ':' with the 'h', then apply again for 'm' etc.
There are additional options, which may be more appropriate/robust etc. depending on your circumstances.
Regular expressions may be useful here, to help you parse/split up such a string.
Or given that you're parsing/outputting times, it may also be worth looking at SimpleDateFormat and its ability to parse/output date/time combinations.
In fact, if you're storing that date as a string, you may want to revist that decision. Storing it as a date object (of whatever variant) is more typesafe, will protect you against invalid values, and allow you to perform arithmetic etc on these.
String[] timeStr = "1:31:25".split(":");
StringBuffer timeStrBuf = new StringBuffer();
timeStrBuf.append(timeStr[0]);
timeStrBuf.append("h ");
timeStrBuf.append(timeStr[1]);
timeStrBuf.append("m ");
timeStrBuf.append(timeStr[2]);
timeStrBuf.append("s");
You can use a regular expression and substitution:
String input = "1:31:25";
String expr = "(\\d+):(\\d+):(\\d+)";
String substitute = "$1h $2m $3s";
String output = input.replaceAll(expr, substitute);
An alternative is to parse and output the String through Date:
DateFormat parseFmt = new SimpleDateFormat("HH:mm:ss");
DateFormat displayFmt = new SimpleDateFormat("H'h' mm\'m' ss's'");
Date d = parseFmt.parse(input);
output = displayFmt.format(d);
Use split()
String s = "1:31:25";
String[] temp = s.split(":");
System.out.println(s[0]+"h"+" "+s[1]+"m"+" "+s[2]+"s");
Related
I want to remove elements a supplied Date Format String - for example convert the format "dd/MM/yyyy" to "MM/yyyy" by removing any non-M/y element.
What I'm trying to do is create a localised month/year format based on the existing day/month/year format provided for the Locale.
I've done this using regular expressions, but the solution seems longer than I'd expect.
An example is below:
public static void main(final String[] args) {
System.out.println(filterDateFormat("dd/MM/yyyy HH:mm:ss", 'M', 'y'));
System.out.println(filterDateFormat("MM/yyyy/dd", 'M', 'y'));
System.out.println(filterDateFormat("yyyy-MMM-dd", 'M', 'y'));
}
/**
* Removes {#code charsToRetain} from {#code format}, including any redundant
* separators.
*/
private static String filterDateFormat(final String format, final char...charsToRetain) {
// Match e.g. "ddd-"
final Pattern pattern = Pattern.compile("[" + new String(charsToRetain) + "]+\\p{Punct}?");
final Matcher matcher = pattern.matcher(format);
final StringBuilder builder = new StringBuilder();
while (matcher.find()) {
// Append each match
builder.append(matcher.group());
}
// If the last match is "mmm-", remove the trailing punctuation symbol
return builder.toString().replaceFirst("\\p{Punct}$", "");
}
Let's try a solution for the following date format strings:
String[] formatStrings = { "dd/MM/yyyy HH:mm:ss",
"MM/yyyy/dd",
"yyyy-MMM-dd",
"MM/yy - yy/dd",
"yyabbadabbadooMM" };
The following will analyze strings for a match, then print the first group of the match.
Pattern p = Pattern.compile(REGEX);
for(String formatStr : formatStrings) {
Matcher m = p.matcher(formatStr);
if(m.matches()) {
System.out.println(m.group(1));
}
else {
System.out.println("Didn't match!");
}
}
Now, there are two separate regular expressions I've tried. First:
final String REGEX = "(?:[^My]*)([My]+[^\\w]*[My]+)(?:[^My]*)";
With program output:
MM/yyyy
MM/yyyy
yyyy-MMM
Didn't match!
Didn't match!
Second:
final String REGEX = "(?:[^My]*)((?:[My]+[^\\w]*)+[My]+)(?:[^My]*)";
With program output:
MM/yyyy
MM/yyyy
yyyy-MMM
MM/yy - yy
Didn't match!
Now, let's see what the first regex actually matches to:
(?:[^My]*)([My]+[^\\w]*[My]+)(?:[^My]*) First regex =
(?:[^My]*) Any amount of non-Ms and non-ys (non-capturing)
([My]+ followed by one or more Ms and ys
[^\\w]* optionally separated by non-word characters
(implying they are also not Ms or ys)
[My]+) followed by one or more Ms and ys
(?:[^My]*) finished by any number of non-Ms and non-ys
(non-capturing)
What this means is that at least 2 M/ys are required to match the regex, although you should be careful that something like MM-dd or yy-DD will match as well, because they have two M-or-y regions 1 character long. You can avoid getting into trouble here by just keeping a sanity check on your date format string, such as:
if(formatStr.contains('y') && formatStr.contains('M') && m.matches())
{
String yMString = m.group(1);
... // other logic
}
As for the second regex, here's what it means:
(?:[^My]*)((?:[My]+[^\\w]*)+[My]+)(?:[^My]*) Second regex =
(?:[^My]*) Any amount of non-Ms and non-ys
(non-capturing)
( ) followed by
(?:[My]+ )+[My]+ at least two text segments consisting of
one or more Ms or ys, where each segment is
[^\\w]* optionally separated by non-word characters
(?:[^My]*) finished by any number of non-Ms and non-ys
(non-capturing)
This regex will match a slightly broader series of strings, but it still requires that any separations between Ms and ys be non-words ([^a-zA-Z_0-9]). Additionally, keep in mind that this regex will still match "yy", "MM", or similar strings like "yyy", "yyyy"..., so it would be useful to have a sanity check as described for the previous regular expression.
Additionally, here's a quick example of how one might use the above to manipulate a single date format string:
LocalDateTime date = LocalDateTime.now();
String dateFormatString = "dd/MM/yyyy H:m:s";
System.out.println("Old Format: \"" + dateFormatString + "\" = " +
date.format(DateTimeFormatter.ofPattern(dateFormatString)));
Pattern p = Pattern.compile("(?:[^My]*)([My]+[^\\w]*[My]+)(?:[^My]*)");
Matcher m = p.matcher(dateFormatString);
if(dateFormatString.contains("y") && dateFormatString.contains("M") && m.matches())
{
dateFormatString = m.group(1);
System.out.println("New Format: \"" + dateFormatString + "\" = " +
date.format(DateTimeFormatter.ofPattern(dateFormatString)));
}
else
{
throw new IllegalArgumentException("Couldn't shorten date format string!");
}
Output:
Old Format: "dd/MM/yyyy H:m:s" = 14/08/2019 16:55:45
New Format: "MM/yyyy" = 08/2019
I'll try to answer with the understanding of my question : how do I remove from a list/table/array of String, elements that does not exactly follow the patern 'dd/MM'.
so I'm looking for a function that looks like
public List<String> removeUnWantedDateFormat(List<String> input)
We can expect, from my knowledge on Dateformat, only 4 possibilities that you would want, hoping i dont miss any, which are "MM/yyyy", "MMM/yyyy", "MM/yy", "MM/yyyy". So that we know what we are looking for we can do an easy function.
public List<String> removeUnWantedDateFormat(List<String> input) {
String s1 = "MM/yyyy";
string s2 = "MMM/yyyy";
String s3 = "MM/yy";
string s4 = "MMM/yy";
for (String format:input) {
if (!s1.equals(format) && s2.equals(format) && s3.equals(format) && s4.equals(format))
input.remove(format);
}
return input;
}
Better not to use regex if you can, it costs a lot of resources. And great improvement would be to use an enum of the date format you accept, like this you have better control over it, and even replace them.
Hope this will help, cheers
edit: after i saw the comment, i think it would be better to use contains instead of equals, should work like a charm and instead of remove,
input = string expected.
so it would looks more like:
public List<String> removeUnWantedDateFormat(List<String> input) {
List<String> comparaisons = new ArrayList<>();
comparaison.add("MMM/yyyy");
comparaison.add("MMM/yy");
comparaison.add("MM/yyyy");
comparaison.add("MM/yy");
for (String format:input) {
for(String comparaison: comparaisons)
if (format.contains(comparaison)) {
format = comparaison;
break;
}
}
return input;
}
I want to remove a part of string from one character, that is:
Source string:
manchester united (with nice players)
Target string:
manchester united
There are multiple ways to do it. If you have the string which you want to replace you can use the replace or replaceAll methods of the String class. If you are looking to replace a substring you can get the substring using the substring API.
For example
String str = "manchester united (with nice players)";
System.out.println(str.replace("(with nice players)", ""));
int index = str.indexOf("(");
System.out.println(str.substring(0, index));
To replace content within "()" you can use:
int startIndex = str.indexOf("(");
int endIndex = str.indexOf(")");
String replacement = "I AM JUST A REPLACEMENT";
String toBeReplaced = str.substring(startIndex + 1, endIndex);
System.out.println(str.replace(toBeReplaced, replacement));
String Replace
String s = "manchester united (with nice players)";
s = s.replace(" (with nice players)", "");
Edit:
By Index
s = s.substring(0, s.indexOf("(") - 1);
Use String.Replace():
http://www.daniweb.com/software-development/java/threads/73139
Example:
String original = "manchester united (with nice players)";
String newString = original.replace(" (with nice players)","");
originalString.replaceFirst("[(].*?[)]", "");
https://ideone.com/jsZhSC
replaceFirst() can be replaced by replaceAll()
Using StringBuilder, you can replace the following way.
StringBuilder str = new StringBuilder("manchester united (with nice players)");
int startIdx = str.indexOf("(");
int endIdx = str.indexOf(")");
str.replace(++startIdx, endIdx, "");
You should use the substring() method of String object.
Here is an example code:
Assumption: I am assuming here that you want to retrieve the string till the first parenthesis
String strTest = "manchester united(with nice players)";
/*Get the substring from the original string, with starting index 0, and ending index as position of th first parenthesis - 1 */
String strSub = strTest.subString(0,strTest.getIndex("(")-1);
I would at first split the original string into an array of String with a token " (" and the String at position 0 of the output array is what you would like to have.
String[] output = originalString.split(" (");
String result = output[0];
Using StringUtils from commons lang
A null source string will return null. An empty ("") source string will return the empty string. A null remove string will return the source string. An empty ("") remove string will return the source string.
String str = StringUtils.remove("Test remove", "remove");
System.out.println(str);
//result will be "Test"
If you just need to remove everything after the "(", try this. Does nothing if no parentheses.
StringUtils.substringBefore(str, "(");
If there may be content after the end parentheses, try this.
String toRemove = StringUtils.substringBetween(str, "(", ")");
String result = StringUtils.remove(str, "(" + toRemove + ")");
To remove end spaces, use str.trim()
Apache StringUtils functions are null-, empty-, and no match- safe
Kotlin Solution
If you are removing a specific string from the end, use removeSuffix (Documentation)
var text = "one(two"
text = text.removeSuffix("(two") // "one"
If the suffix does not exist in the string, it just returns the original
var text = "one(three"
text = text.removeSuffix("(two") // "one(three"
If you want to remove after a character, use
// Each results in "one"
text = text.replaceAfter("(", "").dropLast(1) // You should check char is present before `dropLast`
// or
text = text.removeRange(text.indexOf("("), text.length)
// or
text = text.replaceRange(text.indexOf("("), text.length, "")
You can also check out removePrefix, removeRange, removeSurrounding, and replaceAfterLast which are similar
The Full List is here: (Documentation)
// Java program to remove a substring from a string
public class RemoveSubString {
public static void main(String[] args) {
String master = "1,2,3,4,5";
String to_remove="3,";
String new_string = master.replace(to_remove, "");
// the above line replaces the t_remove string with blank string in master
System.out.println(master);
System.out.println(new_string);
}
}
You could use replace to fix your string. The following will return everything before a "(" and also strip all leading and trailing whitespace. If the string starts with a "(" it will just leave it as is.
str = "manchester united (with nice players)"
matched = str.match(/.*(?=\()/)
str.replace(matched[0].strip) if matched
I'm making a date extractor using regex in java. Problem is that date is 20-05-2014 and my program is extracting 0-5-14. In short, how can I get the character on which I'm checking the second character of date?
int count = 0;
String data = "HellowRoldsThisis20-05-2014. farhan_rock#gmail.comHellowRoldsThisis.farhan#gmail.com";
String regexOfDate = "((?<=[0])[1-9]{2})|((?<=[12])[0-9])|((?<=[3])[01])\\.\\-\\_((?<=[0])[1-9])|((?<=[1])[0-2])\\.\\-\\_((?<=[2])[0-9]{4})"; \\THE PROBLEM
String[] extractedDate = new String[1000];
Pattern patternDate = Pattern.compile(regexOfDate);
Matcher matcherDate = patternDate.matcher(data);
while(matcherDate.find()){
System.out.println("Date "+count+"Start: "+matcherDate.start());
System.out.println("Date "+count+"End : "+matcherDate.end());
extractedDate[count] = data.substring(matcherDate.start(), matcherDate.end());
System.out.println("Date Extracted: "+extractedDate[count]);
}
You can try the regular expression:
// (0[1-9]|[12][0-9]|[3][01])[._-](0[1-9]|1[0-2])[._-](2[0-9]{3})
"(0[1-9]|[12][0-9]|[3][01])[._-](0[1-9]|1[0-2])[._-](2[0-9]{3})"
A single regex o match valid dates is awful.
I'd do:
String regexOfDate = "(?<!\\d)\\d{2}[-_.]\\d{2}[-_.]\\d{4}(?!\\d)";
to extract the potential date, then test if it is valid.
I have the following code and in need to replace the value on time from PT14H01M00S to 14:01:00 the following code is omit the first two char but I get 14H01M00S ,there is no way to do that without using string builder?
String time = "PT14H01M00S";
String substring = time .substring(2);
substring.replace("H", ":");
substring.replace("M", ":");
substring.replace("S", "");
System.out.println(substring);
You could use a regex and replace
^..(\d\d)H(\d\d)M(\d\d)S$
with
$1:$2:$3
(I leave the details of the code as an exercise for the reader.)
you forgot to do
String time = "PT14H01M00S";
String substring = time .substring(2);
substring = substring.replace("H", ":");
substring = substring.replace("M", ":");
substring = substring.replace("S", "");
System.out.println(substring);
so the substring is not getting the new value returned from replace method
ran it in here and got
It seems like you are trying to parse and format a JodaTime Period. You should not do it using the String class API. Use appropriate formatter already provided in JodaTime API.
You should build 2 PeriodFormatters using PeriodFormatterBuilder class, one for parsing the given string into a Period, and then second for formatting the Period to the required format:
String periodString = "PT14H01M00S";
PeriodFormatter parser = new PeriodFormatterBuilder()
.appendLiteral("PT")
.appendHours().appendSuffix("H")
.appendMinutes().appendSuffix("M")
.appendSeconds().appendSuffix("S")
.toFormatter();
PeriodFormatter formatter = new PeriodFormatterBuilder()
.minimumPrintedDigits(2)
.printZeroAlways()
.appendHours()
.appendSeparator(":")
.appendMinutes()
.appendSeparator(":")
.appendSeconds()
.toFormatter();
System.out.println(formatter.print(parser.parsePeriod(periodString)));
Output:
14:01:00
use this code instead :
String time = "PT14H01M00S";
String substring = time .substring(2);
substring = substring.replace("H", ":");
substring = substring.replace("M", ":");
substring = substring.replace("S", "");
the replace method doesn't change the string it was called upon, it returns a new string.
So what you want is:
String time = "PT14H01M00S";
String substring = time .substring(2);
substring = substring.replace("H", ":");
substring = substring.replace("M", ":");
substring = substring.replace("S", "");
I recommend the use of regular expressions to do this kind of tasks. They are very powerful to search and replace patterns of text.
I thinks this should work
String time = "PT14H01M00S".substring(2, time.length - 1).replace(/H|M/, ":");
use this code instead
String substring = time .substring(2);
substring = substring.replaceAll("[HM]",":").replace("S", "");
Hopefully somebody can help me with this.. or at least point me in the right direction.
First off, I have a bunch of files with names such as:
vendor.2012-07-25
vendor.2012-07-25 2
ven_dor.2012-05-18
ven_dor.2012-05-18 2
Basically a vendor name (Sometimes one word, sometimes two with an underscore) + (period ".") + (year) + (month) + (day). Year, month, day are separated by (-). Possibly multiple files with the same name, denoted by a 2/3/4 etc after the date.
I obtain these as strings by doing file.getName(); where 'file' is the selected file from a JFileChooser
Then I need to chart some of the data based on date. Should I try to split the initial file name string by a "." first, so that the vendor and date are separated, and then split/divide up the remaining part by "-" to have the individual values for year/month/day?
I was thinking this could be a regex thing, but I'm pretty weak in that area.. so the double splitting is what I came up with. Anybody have input or suggestions? Thanks!
Indeed, you can use a regular expression:
String s = "vendor.2012-07-25 2";
Pattern p = Pattern.compile("([^.]+)\\.(\\d{4})-(\\d{2})-(\\d{2}) ?(\\d?)");
Matcher m = p.matcher(s);
if (m.find()) {
String vendorName = m.group(1);
String year = m.group(2);
String month = m.group(3);
String day = m.group(4);
String multipleFiles = m.groupCount() > 4 ? m.group(5) : "";
System.out.printf("%s %s %s %s %s", vendorName, year, month, day, multipleFiles);
}
Each expression wrapped with parentheses () is called a capturing group, and it basically tells the regex engine to save its content, so that it can be retrieved later on.
In sum, here's what each capturing group does:
([^.]+) - Everything but a dot (.), so we are basically capturing the vendor name part;
(\\d{4}) - \d matches a digit. \d{4} matches 4 digits (year);
(\\d{2}) - Month;
(\\d{2}) - Day;
(\\d?) - Matches an optional (?) last digit.
If you want to parse the date part as a java.Util.Date instance, you can use a single capturing group for it, and then use SimpleDateFormat:
Pattern p = Pattern.compile("([^.]+)\\.(\\d{4}-\\d{2}-\\d{2}) ?(\\d?)");
Matcher m = p.matcher(s);
if (m.find()) {
String vendorName = m.group(1);
String dateString = m.group(2);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String multipleFiles = m.groupCount() > 2 ? m.group(3) : "";
}
String.split on the . (it will probably require escaping). Take the dotSplitString[1] as being the part after vendor. or ven_dor.
Split that part on space (spaceSplitString).
Parse the first part using DateFormat.parse(String) to get a Date
If the 2nd part (of the spaceSplitString) is present, use Integer.parseInt(spaceSplitString[1])
Java API String Tokenizer class
What you can do is:
tokenizer = new StringTokenizer(file.getName(), ".");
tokenizer.nextElement();
you get the picture, Or you can use Scanner to parse it as well
I tend to make use of StringTokenizers in my code a lot. To tokenize the above example you could use something akin to the following:
StringTokenizer tok = new StringTokenizer(filename,".-"); //tokenizes both on '.' and '-'
String name = tok.nextToken();
int year = Integer.parseInt(tok.nextToken());
int month = Integer.parseInt(tok.nextToken());
int day = Integer.parseInt(tok.nextToken());
int cnt = 1; //default one copy of the file
if(tok.hasMoreTokens()){
cnt = Integer.parseInt(tok.nextToken());
}
...and so on.
However I endorse the use of the regex solution above, if not only because it looks less comprehensible to a layman. Just including this here for completeness.