Let's assume a string consists of two parts, day and date.
String arr[] = { "Tuesday 8/11/22", "Monday 15/3/21", "Friday 20/5/21" };
How can I only print out the latter part (date part) on console?
I recommend you use the date-time API instead of performing string manipulation of the elements. The string manipulation will not give you all the benefits that you can get by the specialized date-time API.
Bonus
You get your dates validated free of cost e.g. one of your dates, Friday 20/5/21 is incorrect. This date was Thursday and the java.time API can perform this check for you automatically.
Demo:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.Locale;
class Main {
public static void main(String[] args) {
String arr[] = { "Tuesday 8/11/22", "Monday 15/3/21", "Friday 20/5/21" };
DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEEE d/M/uu", Locale.ENGLISH);
for (String s : arr) {
LocalDate date = LocalDate.parse(s, parser);
// Now you can get individual units from date in a variety of ways
System.out.println(date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH));
System.out.println(date.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.ENGLISH));
System.out.println(date.getYear());
// You can also format it in the desired ways
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/uu", Locale.ENGLISH);
String formatted = date.format(formatter);
System.out.println(formatted);
}
}
}
Output:
Tuesday
Tue
2022
8/11/22
Monday
Mon
2021
15/3/21
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Friday 20/5/21' could not be parsed: Conflict found: Field DayOfWeek 4 differs from DayOfWeek 5 derived from 2021-05-20
at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2023)
Learn more about the modern Date-Time API from Trail: Date Time.
As long as the day and date will stay in that format you can use the split() function:
class DateSplit {
public static void main(String[] args) {
String a = "Tuesday 8/11/22";
String[] result = a.split(" ");
System.out.println(result[1]);
}
}
where the delimiter splitting the string is the whitespace character.
for(String str : arr) {
System.out.println(str.split(" ")[1])
}
public class Main {
public static void main(String[] args) {
String arr[] = { "Tuesday 8/11/22", "Monday 15/3/21", "Friday 20/5/21" };
for(int count = 0; count < arr.length; count++) {
String[] s = arr[count].split(" ");
System.out.println(s[1]);
}
}
}
I have string of date with format like this: 19930508. I want to use only 0508 from this string which is MMdd and than compare it with today's MMdd.
The code i am using is:
Date todaysDate = new Date();
String dateTest = "19930508";
SimpleDateFormat df = new SimpleDateFormat("MMdd");
Date date = df.parse(dateTest);
String birthDate = df.format(date);
if(birthDate.equals(df.format(todaysDate))){do something}
The problem is the that birthdate formate is not working correctly neither todaysDate.
Date date var print nothing and birthDate string print 0220 which makes no sense to me.
Anyone with anyidea how can i work with this kind of formating and compare it with todaysdate ?
Using java.time from Java 8:
MonthDay now = MonthDay.now();
String dateTest = "19930508";
DateTimeFormatter yearMonthDayFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
MonthDay birthDay = MonthDay.parse(dateTest, yearMonthDayFormatter);
if (birthDay.equals(now)) {
System.out.println("same MMdd");
} else {
System.out.println("different MMdd");
}
// works with java6
public class AnniversaryChecker {
private final String dayInYear;
public AnniversaryChecker() {
this(new SimpleDateFormat("MMdd").format(new Date()));
}
// VisibleForTesting
public AnniversaryChecker(String mmdd) {
this.dayInYear = mmdd;
}
public boolean isAnniversary(String yyyyMMdd) {
return yyyyMMdd.endsWith(dayInYear);
}
}
I am trying to parse some dates that are coming out of a document. It would appear users have entered these dates in a similar but not exact format.
here are the formats:
9/09
9/2009
09/2009
9/1/2009
9-1-2009
What is the best way to go about trying to parse all of these? These seem to be the most common, but I guess what is hanging me up is that if i have a pattern of "M/yyyy" wont that always catch before "MM/yyyy" Do I have to set up my try/catch blocks nested in a least restrictive to most restrictive way? it seems like it sure is going to take a lot of code duplication to get this right.
You'll need to use a different SimpleDateFormat object for each different pattern. That said, you don't need that many different ones, thanks to this:
Number: For formatting, the number of pattern letters is the minimum number of digits, and shorter numbers are zero-padded to this amount. For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.
So, you'll need these formats:
"M/y" (that covers 9/09, 9/2009, and 09/2009)
"M/d/y" (that covers 9/1/2009)
"M-d-y" (that covers 9-1-2009)
So, my advice would be to write a method that works something like this (untested):
// ...
List<String> formatStrings = Arrays.asList("M/y", "M/d/y", "M-d-y");
// ...
Date tryParse(String dateString)
{
for (String formatString : formatStrings)
{
try
{
return new SimpleDateFormat(formatString).parse(dateString);
}
catch (ParseException e) {}
}
return null;
}
What about just defining multiple patterns? They might come from a config file containing known patterns, hard coded it reads like:
List<SimpleDateFormat> knownPatterns = new ArrayList<SimpleDateFormat>();
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm.ss'Z'"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
for (SimpleDateFormat pattern : knownPatterns) {
try {
// Take a try
return new Date(pattern.parse(candidate).getTime());
} catch (ParseException pe) {
// Loop on
}
}
System.err.println("No known Date format found: " + candidate);
return null;
Matt's approach above is fine, but please be aware that you will run into problems if you use it to differentiate between dates of the format y/M/d and d/M/y. For instance, a formatter initialised with y/M/d will accept a date like 01/01/2009 and give you back a date which is clearly not what you wanted. I fixed the issue as follows, but I have limited time and I'm not happy with the solution for 2 main reasons:
It violates one of Josh Bloch's quidelines, specifically 'don't use exceptions to handle program flow'.
I can see the getDateFormat() method becoming a bit of a nightmare if you needed it to handle lots of other date formats.
If I had to make something that could handle lots and lots of different date formats and needed to be highly performant, then I think I would use the approach of creating an enum which linked each different date regex to its format. Then use MyEnum.values() to loop through the enum and test with if(myEnum.getPattern().matches(date)) rather than catching a dateformatexception.
Anway, that being said, the following can handle dates of the formats 'y/M/d' 'y-M-d' 'y M d' 'd/M/y' 'd-M-y' 'd M y' and all other variations of those which include time formats as well:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static final String[] timeFormats = {"HH:mm:ss","HH:mm"};
private static final String[] dateSeparators = {"/","-"," "};
private static final String DMY_FORMAT = "dd{sep}MM{sep}yyyy";
private static final String YMD_FORMAT = "yyyy{sep}MM{sep}dd";
private static final String ymd_template = "\\d{4}{sep}\\d{2}{sep}\\d{2}.*";
private static final String dmy_template = "\\d{2}{sep}\\d{2}{sep}\\d{4}.*";
public static Date stringToDate(String input){
Date date = null;
String dateFormat = getDateFormat(input);
if(dateFormat == null){
throw new IllegalArgumentException("Date is not in an accepted format " + input);
}
for(String sep : dateSeparators){
String actualDateFormat = patternForSeparator(dateFormat, sep);
//try first with the time
for(String time : timeFormats){
date = tryParse(input,actualDateFormat + " " + time);
if(date != null){
return date;
}
}
//didn't work, try without the time formats
date = tryParse(input,actualDateFormat);
if(date != null){
return date;
}
}
return date;
}
private static String getDateFormat(String date){
for(String sep : dateSeparators){
String ymdPattern = patternForSeparator(ymd_template, sep);
String dmyPattern = patternForSeparator(dmy_template, sep);
if(date.matches(ymdPattern)){
return YMD_FORMAT;
}
if(date.matches(dmyPattern)){
return DMY_FORMAT;
}
}
return null;
}
private static String patternForSeparator(String template, String sep){
return template.replace("{sep}", sep);
}
private static Date tryParse(String input, String pattern){
try{
return new SimpleDateFormat(pattern).parse(input);
}
catch (ParseException e) {}
return null;
}
}
If working in Java 1.8 you can leverage the DateTimeFormatterBuilder
public static boolean isTimeStampValid(String inputString)
{
DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ofPattern("" + "[yyyy-MM-dd'T'HH:mm:ss.SSSZ]" + "[yyyy-MM-dd]"));
DateTimeFormatter dateTimeFormatter = dateTimeFormatterBuilder.toFormatter();
try {
dateTimeFormatter.parse(inputString);
return true;
} catch (DateTimeParseException e) {
return false;
}
}
See post: Java 8 Date equivalent to Joda's DateTimeFormatterBuilder with multiple parser formats?
In Apache commons lang, DateUtils class we have a method called parseDate. We can use this for parsing the date.
Also another library Joda-time also have the method to parse the date.
Here is the complete example (with main method) which can be added as a utility class in your project. All the format mentioned in SimpleDateFormate API is supported in the below method.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
public class DateUtility {
public static Date parseDate(String inputDate) {
Date outputDate = null;
String[] possibleDateFormats =
{
"yyyy.MM.dd G 'at' HH:mm:ss z",
"EEE, MMM d, ''yy",
"h:mm a",
"hh 'o''clock' a, zzzz",
"K:mm a, z",
"yyyyy.MMMMM.dd GGG hh:mm aaa",
"EEE, d MMM yyyy HH:mm:ss Z",
"yyMMddHHmmssZ",
"yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
"YYYY-'W'ww-u",
"EEE, dd MMM yyyy HH:mm:ss z",
"EEE, dd MMM yyyy HH:mm zzzz",
"yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm:ss.SSSzzzz",
"yyyy-MM-dd'T'HH:mm:sszzzz",
"yyyy-MM-dd'T'HH:mm:ss z",
"yyyy-MM-dd'T'HH:mm:ssz",
"yyyy-MM-dd'T'HH:mm:ss",
"yyyy-MM-dd'T'HHmmss.SSSz",
"yyyy-MM-dd",
"yyyyMMdd",
"dd/MM/yy",
"dd/MM/yyyy"
};
try {
outputDate = DateUtils.parseDate(inputDate, possibleDateFormats);
System.out.println("inputDate ==> " + inputDate + ", outputDate ==> " + outputDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return outputDate;
}
public static String formatDate(Date date, String requiredDateFormat) {
SimpleDateFormat df = new SimpleDateFormat(requiredDateFormat);
String outputDateFormatted = df.format(date);
return outputDateFormatted;
}
public static void main(String[] args) {
DateUtility.parseDate("20181118");
DateUtility.parseDate("2018-11-18");
DateUtility.parseDate("18/11/18");
DateUtility.parseDate("18/11/2018");
DateUtility.parseDate("2018.11.18 AD at 12:08:56 PDT");
System.out.println("");
DateUtility.parseDate("Wed, Nov 18, '18");
DateUtility.parseDate("12:08 PM");
DateUtility.parseDate("12 o'clock PM, Pacific Daylight Time");
DateUtility.parseDate("0:08 PM, PDT");
DateUtility.parseDate("02018.Nov.18 AD 12:08 PM");
System.out.println("");
DateUtility.parseDate("Wed, 18 Nov 2018 12:08:56 -0700");
DateUtility.parseDate("181118120856-0700");
DateUtility.parseDate("2018-11-18T12:08:56.235-0700");
DateUtility.parseDate("2018-11-18T12:08:56.235-07:00");
DateUtility.parseDate("2018-W27-3");
}
}
Best and Simple Java 8 answer (from https://stackoverflow.com/a/59546290/2131040)
final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);
This solution checks all the possible formats before throwing an exception. This solution is more convenient if you are trying to test for multiple date formats.
Date extractTimestampInput(String strDate){
final List<String> dateFormats = Arrays.asList("yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd");
for(String format: dateFormats){
SimpleDateFormat sdf = new SimpleDateFormat(format);
try{
return sdf.parse(strDate);
} catch (ParseException e) {
//intentionally empty
}
}
throw new IllegalArgumentException("Invalid input for date. Given '"+strDate+"', expecting format yyyy-MM-dd HH:mm:ss.SSS or yyyy-MM-dd.");
}
For the modern answer I am ignoring the requirement to use SimpleDateFormat. While using this class for parsing was a good idea in 2010 when this question was asked, it is now long outdated. The replacement, DateTimeFormatter, came out in 2014. The idea in the following is pretty much the same as in the accepted answer.
private static DateTimeFormatter[] parseFormatters = Stream.of("M/yy", "M/y", "M/d/y", "M-d-y")
.map(DateTimeFormatter::ofPattern)
.toArray(DateTimeFormatter[]::new);
public static YearMonth parseYearMonth(String input) {
for (DateTimeFormatter formatter : parseFormatters) {
try {
return YearMonth.parse(input, formatter);
} catch (DateTimeParseException dtpe) {
// ignore, try next format
}
}
throw new IllegalArgumentException("Could not parse " + input);
}
This parses each of the input strings from the question into a year-month of 2009-09. It’s important to try the two-digit year first since "M/y" could also parse 9/09, but into 0009-09 instead.
A limitation of the above code is it ignores the day-of-month from the strings that have one, like 9/1/2009. Maybe it’s OK as long as most formats have only month and year. To pick it up, we’d have to try LocalDate.parse() rather then YearMonth.parse() for the formats that include d in the pattern string. Surely it can be done.
I'm solved this problem more simple way using regex
fun parseTime(time: String?): Long {
val longRegex = "\\d{4}+-\\d{2}+-\\d{2}+\\w\\d{2}:\\d{2}:\\d{2}.\\d{3}[Z]\$"
val shortRegex = "\\d{4}+-\\d{2}+-\\d{2}+\\w\\d{2}:\\d{2}:\\d{2}Z\$"
val longDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssXXX")
val shortDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
return when {
Pattern.matches(longRegex, time) -> longDateFormat.parse(time).time
Pattern.matches(shortRegex, time) -> shortDateFormat.parse(time).time
else -> throw InvalidParamsException(INVALID_TIME_MESSAGE, null)
}
}
Implemented the same in scala, Please help urself with converting to Java, the core logic and functions used stays the same.
import java.text.SimpleDateFormat
import org.apache.commons.lang.time.DateUtils
object MultiDataFormat {
def main(args: Array[String]) {
val dates =Array("2015-10-31","26/12/2015","19-10-2016")
val possibleDateFormats:Array[String] = Array("yyyy-MM-dd","dd/MM/yyyy","dd-MM-yyyy")
val sdf = new SimpleDateFormat("yyyy-MM-dd") //change it as per the requirement
for (date<-dates) {
val outputDate = DateUtils.parseDateStrictly(date, possibleDateFormats)
System.out.println("inputDate ==> " + date + ", outputDate ==> " +outputDate + " " + sdf.format(outputDate) )
}
}
}
Using DateTimeFormatter it can be achieved as below:
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.TimeZone;
public class DateTimeFormatTest {
public static void main(String[] args) {
String pattern = "[yyyy-MM-dd[['T'][ ]HH:mm:ss[.SSSSSSSz][.SSS[XXX][X]]]]";
String timeSample = "2018-05-04T13:49:01.7047141Z";
SimpleDateFormat simpleDateFormatter = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
TemporalAccessor accessor = formatter.parse(timeSample);
ZonedDateTime zTime = LocalDateTime.from(accessor).atZone(ZoneOffset.UTC);
Date date=new Date(zTime.toEpochSecond()*1000);
simpleDateFormatter.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
System.out.println(simpleDateFormatter.format(date));
}
}
Pay attention at String pattern, this is the combination of multiple patterns. In open [ and close ] square brackets you can mention any kind of patterns.
I was having multiple date formats into json, and was extracting csv with universal format. I looked multiple places, tried different ways, but at the end I'm able to convert with the following simple code.
private String getDate(String anyDateFormattedString) {
#SuppressWarnings("deprecation")
Date date = new Date(anyDateFormattedString);
SimpleDateFormat dateFormat = new SimpleDateFormat(yourDesiredDateFormat);
String convertedDate = dateFormat.format(date);
return convertedDate;
}
I have an date object from which i need to getTime(). The issue is it always shows 00:00:00.
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm:ss");
long date = Utils.getDateObject(DateObject).getTime();
String time = localDateFormat.format(date);
Why is the time always '00:00:00'. Should i append Time to my Date Object
You should pass the actual Date object into format, not a long:
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm:ss");
String time = localDateFormat.format(Utils.getDateObject(DateObject));
Assuming that whatever Utils.getDateObject(DateObject) is actually returns a Date (which is implied by your question but not actually stated), that should work fine.
For example, this works perfectly:
import java.util.Date;
import java.text.SimpleDateFormat;
public class SDF {
public static final void main(String[] args) {
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm:ss");
String time = localDateFormat.format(new Date());
System.out.println(time);
}
}
Re your comment below:
Thanks TJ, but actually i am still getting 00:00:00 as time.
That means your Date object has zeroes for hours, minutes, and seconds, like so:
import java.util.Date;
import java.text.SimpleDateFormat;
public class SDF {
public static final void main(String[] args) {
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm:ss");
String time = localDateFormat.format(new Date(2013, 4, 17)); // <== Only changed line (and using a deprecated API)
System.out.println(time);
}
}
Apart from above solution , you can also use calendar class if you don't have specific requirement
Calendar cal1 =new GregorianCalendar() or Calendar.getInstance();
SimpleDateFormat date_format = new SimpleDateFormat("HH:mm:ss");
System.out.println(date_format.format(cal1.getTime()));
For example, you can use next code:
public static int getNotesIndexByTime(Date aDate){
int ret = 0;
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH");
String sTime = localDateFormat.format(aDate);
int iTime = Integer.parseInt(sTime);
return iTime;// count of hours 0-23
}