Possible to create a Java.time.LocalDate object from a String? - java

I have been trying to use the date.format(DateTimeFormatter formatter) method to format a list of date strings, where 'date' is a java.time.LocalDate object, for example. The problem is, I cannot find a straight-forward way to create a Year object from a string. For instance, if I have the string yearString = "90". I would like to create a Year object that is equal to this value, and then use the format method to output yearStringNew = "1990". The closest I see to a public constructor is the now() function which returns the current time.
I have also looked into creating a Calendar object and then creating a format-able date object there, but I can only create a Java.util.Date object – as opposed to an object in the Java.time package which could then ideally be formatted by the format function. Am I missing something here?
FYI I'm referencing the Java 8 SDK javadoc https://docs.oracle.com/javase/8/docs/api/
Thank you for your time.
EDIT: Per the request of another user, I have posted my code below; this is the closest I have come to accomplishing what I'm looking for:
//Module 3:
//Format Date Segments
package challenge245E;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class TestClass3 {
public static void main(String[] args) throws ParseException {
DateFormatter dateFormatter = new DateFormatter();
String myGroupedSlices [][] =
{
{"1990", "12", "06"},
{"12","6", "90"}
};
dateFormatter.formatDates(myGroupedSlices);
}
}
class DateFormatter {
public Date[][] formatDates(String[][] groupedDates) throws ParseException {
Date[][] formattedDates = new Date[groupedDates.length][3];
DateFormat yearFormat = new SimpleDateFormat("YYYY");
DateFormat monthFormat = new SimpleDateFormat("MM");
DateFormat dayFormat = new SimpleDateFormat("dd");
//iterate through each groupedSlices array
for (int i=0; i<groupedDates.length;i++) {
//Conditions
if (groupedDates[i][0].length()<3) {
//MDDYY format: if date[0].length < 3
//Re-arrange into YDM order
String m = groupedDates[i][0];
String y = groupedDates[i][2];
groupedDates[i][0] = y;
groupedDates[i][2] = m;
//convert dates to correct format
formattedDates[i][0] = yearFormat.parse(groupedDates[i][0]);
formattedDates[i][1] = monthFormat.parse(groupedDates[i][1]);
formattedDates[i][2] = dayFormat.parse(groupedDates[i][2]);
//testing if block
System.out.println("MDY Order: " + Arrays.toString(formattedDates[i]));
}
if (groupedDates[i][0].length()>3) {
//YYYYMMDD format: if date[0].length > 3
//convert dates to correct format
formattedDates[i][0] = yearFormat.parse(groupedDates[i][0]);
formattedDates[i][1] = monthFormat.parse(groupedDates[i][1]);
formattedDates[i][2] = dayFormat.parse(groupedDates[i][2]);
//testing if block
System.out.println("YMD Order: " + Arrays.toString(formattedDates[i]));
}
}
return formattedDates;
}
}

If I understand your requirement correctly, have a look at the LocalDate.parse() methods.
Example:
LocalDate date = LocalDate.parse("1990-01-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
int year = date.getYear(); // 1990

Parse Each Number Separately
It’s good to see you using the java.time framework rather than the troublesome old date-time classes. The old java.util.Date/.Calendar classes have been supplanted by the new framework.
The DateTimeFormatter class parses any two digit year as being in the 2000s. From class doc:
If the count of letters is two… will parse using the base value of 2000, resulting in a year within the range 2000 to 2099 inclusive.
To override this behavior, see this Answer by assylias. But that issue may be moot in your case. You already have the individual year, month, and date values isolated. So they need not be parsed together.
I suggest you convert each string into a integer. For the year, if less than 100 then add 1900.
String inputYear = "90";
String inputMonth = "12";
String inputDayOfMonth = "6";
int year = Integer.parseInt( inputYear );
int month = Integer.parseInt( inputMonth );
int dayOfMonth = Integer.parseInt( inputDayOfMonth );
if( year < 100 ) { // If two-digit year, assume the 1900s century. Even better: Never generate two-digit year text!
year = ( year + 1900 );
}
LocalDate localDate = LocalDate.of( year , month , dayOfMonth );

Create an Instance of class GregorianCalendar, set your date in that calendar and then use the method toZonedDateTime(). This will give you ZonedDateTime instance. form it you can use method LocalDate.from(TemporalAccessor temporal) method to get your LocalDate. Here how it might look:
//....
GregorianCalendar calendar = new GregorianCalendar();
// Set the deasired date in your calendar
LocalDate localDate = LocalDate.from(calendar.toZonedDateTime());
//...

import java.time.LocalDate;
public class DaysTilNextMonth {
public static void main(String[] args) {
//create an object for LocalDate class
LocalDate date = LocalDate.now();
//get today's day
int today = date.getDayOfMonth();
//get number of days in the current month
int numOfDaysInMonth = date.lengthOfMonth();
//compute the days left for next month
int dayForNextMonth = numOfDaysInMonth - today;
//display the result
System.out.println("The next month is: " + date.plusMonths(7).getMonth());
System.out.println("We have " + dayForNextMonth + " days left until first day of next month.");
}
}

Related

How to iterate downward from a Date in one year to a Date in a previous year?

I have a beginning date, let us say it is 2020-12-30 08:00:00, and I have an end date, let us say it is 2021-02-11 16:00:00.
I need to get the hours between these days which I do by using:
long diffInHours = TimeUnit.HOURS.convert(Math.abs(closeStoreDateTime.getTime() - openStoreDateTime.getTime()), TimeUnit.MILLISECONDS);
My issue is that as I iterate downward from the end date to the beginning date, I am converting the hour difference between the current hour and the beginning hour into an accurate time to store in a map later on. Like this:
int latestHour = (int) diffInHours;
while (latestHour >= openStoreDateTime.toInstant().atZone(ZoneId.systemDefault()).getHour()) {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(ZoneId.systemDefault()));
String hourConversion;
if (closeStoreDateTime.toInstant().atZone(ZoneId.systemDefault()).getDayOfYear() > openStoreDateTime.toInstant().atZone(ZoneId.systemDefault()).getDayOfYear()) {
if (latestHour > 24) {
calendar.add(Calendar.HOUR_OF_DAY, latestHour);
hourConversion = calendar.get(Calendar.AM_PM) == Calendar.AM ? String.valueOf(calendar.get(Calendar.HOUR)) : String.valueOf(calendar.get(Calendar.HOUR) + 12);
} else {
calendar.add(Calendar.HOUR_OF_DAY, latestHour);
int AM_PM = calendar.get(Calendar.AM_PM);
if (AM_PM == Calendar.AM || (AM_PM == Calendar.PM && calendar.get(Calendar.HOUR) == 12)) {
hourConversion = String.valueOf(calendar.get(Calendar.HOUR));
} else {
hourConversion = String.valueOf(calendar.get(Calendar.HOUR) + 12);
}
}
} else {
hourConversion = String.valueOf(latestHour);
}
This works if the dates are within the same year, but does not work if they are in different years because the day in the begin year (363) is greater than the day in the end year. Does anyone have an idea how to convert hours between 2 different dates into a useable date? Thank you.
If I understand your question correctly, you want a List of date-time values from an end date-time through a start date-time, one for each hour.
Here are some test results.
2021-02-11T16:00
2021-02-11T15:00
2021-02-11T14:00
2021-02-11T13:00
2021-02-11T12:00
...
2020-12-30T12:00
2020-12-30T11:00
2020-12-30T10:00
2020-12-30T09:00
2020-12-30T08:00
Here's runnable code that will do that using the LocalDateTime class. You can display a LocalDateTime value anyway you want using a DateTimeFormatter.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
public class DateIntervals {
public static void main(String[] args) {
String endDateString = "2021-02-11 16:00:00";
String startDateString = "2020-12-30 08:00:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd HH:mm:ss");
LocalDateTime endDate = LocalDateTime.parse(endDateString, formatter);
LocalDateTime startDate = LocalDateTime.parse(startDateString, formatter);
List<LocalDateTime> intervals = new ArrayList<>();
LocalDateTime date = endDate;
while (date.isAfter(startDate)) {
intervals.add(date);
date = date.minusHours(1L);
}
intervals.add(date);
for (int i = 0; i < intervals.size(); i++) {
System.out.println(intervals.get(i));
}
}
}

how can I change only year in date String?

I have java date string.
How can I change its year without changing the month and date.
e.g.
parts1[1]= 2020-1-2;
parts1[2]= 13:48:21;
CreatedDate = parts1[1]+" "+parts1[2];
System.out.println(CreatedDate);
I want to change it to
parts1[1]= 2021-1-2;
parts1[2]= 13:48:21;
CreatedDate = parts1[1]+" "+parts1[2];
System.out.println(CreatedDate);
I basically want to change the year without changing month and date
Can it be done?
java.time
You do not have to split the string and then combine the parts. You can parse the whole string into LocalDateTime and then use LocalDateTime#withYear to get a new instance with the specified year.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String creationDateTime = "2020-1-2 13:48:21";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-M-d H:m:s", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(creationDateTime, dtf);
System.out.println(ldt);
ldt = ldt.withYear(2021);
// Default format
String updatedDateTime = ldt.toString();
System.out.println(updatedDateTime);
// Custom format
updatedDateTime = ldt.format(dtf);
System.out.println(updatedDateTime);
}
}
Output:
2020-01-02T13:48:21
2021-01-02T13:48:21
2021-1-2 13:48:21
Learn more about java.time API from Trail: Date Time.
try:
String[] arrOfStr = parts1[1].split("-", 2);
arrOfStr[0] contains the year
Now you need to parse it as an int (since it's only 4 digits)
int year = Integer.parseInt(arrOfStr[0]);
year now contains the the number 2020.
you can do
year++;
to increase it's value by 1
and to put it back in String format do:
arrOfStr[0] = "" + year;
or
arrOfStr[0] = String.valueOf(year);
to put it all together do this
parts1[1]= arrOfStr[0] + "-" arrOfStr[1]; // 2021-1-2
finally it should look like this:
parts1[1]= 2020-1-2;
parts1[2]= 13:48:21;
String[] arrOfStr = parts1[1].split("-", 2);
int year = Integer.parseInt(arrOfStr[0]);
year++;
arrOfStr[0] = "" + year;
parts1[1]= arrOfStr[0] + "-" + arrOfStr[1];
CreatedDate = parts1[1]+" "+parts1[2];
System.out.println(CreatedDate);

getDay() method to return day of the week for a given date not works

I'm trying to complete the task named Java Date and Time on HackerRank.
Task
You are given a date. You just need to write the method, getDay, which
returns the day on that date.For example, if you are given the date,
August 14th 2017, the method should return MONDAY as the day on that
date.
I tried my best to do the task but I get either the null result or NullPointerException error. I wonder where do I do wrong. Below is my code:
Thanks in advance!
My Code:
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String month = in.next();
String day = in.next();
String year = in.next();
System.out.println(getDay(day, month, year));
}
public static String getDay(String day, String month, String year) {
Calendar cal = Calendar.getInstance();
cal.set(Integer.valueOf(year), (Integer.valueOf(month) - 1), Integer.valueOf(day));
return cal.getDisplayName(cal.get(Calendar.DAY_OF_WEEK), Calendar.LONG, Locale.getDefault());
}
}
Your return is off; you don't want cal.get in the first column of cal.getDisplayName. Currently, I get the month name with your code. Change that to
return cal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault());
And call it like
public static void main(String[] args) {
System.out.println(getDay("14", "8", "2017"));
}
And I get (as expected)
Monday
In new code, I would prefer the new classes in java.time (Java 8+), and a DateTimeFormatter - like,
public static String getDay(String day, String month, String year) {
int y = Integer.parseInt(year), m = Integer.parseInt(month), d = Integer.parseInt(day);
return java.time.format.DateTimeFormatter.ofPattern("EEEE")
.format(LocalDate.of(y, m, d));
}
java.time.LocalDate
The modern approach uses the java.time classes.
Import java.time.* to access LocalDate & DayOfWeek classes.
Write getDay method which should be static because it is called in main method.
Retrieve localDate by using of method which takes 3 arguments in "int" format.
convert the getDay method arguments in int format.
finally retrieve name of that day using getDayOfWeek method.
There is one video on this challenge.
Java Date and Time Hackerrank
LocalDate // Represent a date-only value, without time-of-day and without time zone.
.of( 2018 , 1 , 23 ) // Pass year-month-day, 1-12 for January-December.
.getDayOfWeek() // Obtain a `DayOfWeek` enum object.
.getDisplayName( // Automatically localize the name of the day-of-week.
TextStyle.FULL , // How long or abbreviated.
Locale.US // Or Locale.CANADA_FRENCH or so on.
) // Returns `String` such as `Monday` or `lundi`.
For Java 6 & 7, see the ThreeTen-Backport project. For earlier Android, see the ThreeTenABP project.
if you want to use LocalDate, you can use it this way
import java.time.LocalDate;
public static String getDay(int month, int day, int year) {
return LocalDate.of(year, month, day).getDayOfWeek().name();
}
public static String getDay(int month, int day, int year) {
String res= java.time.format.DateTimeFormatter.ofPattern("EEEE")
.format(java.time.LocalDate.of(year, month, day));
return res; }
must use java.time.LocalDate, if u will use direct LocalDate its show compile time error i.e cannot find symbol, so plz use java.time.
You can use new Java8 DateTime API.
public static String getDay(int day, int month, int year)
{
LocalDate dt=LocalDate.of(year, month, day);
System.out.println("day: " + dt.getDayOfWeek().toString());
return dt.getDayOfWeek().toString();
}
A LocalDate is a date without time of day, so fine for our purpose. The of factory method constructs the date that we want. Contrary to the Calendar class used in the question it numbers the months sanely from 1 for January through 12 for December. A LocalDate has a getter for day of week. It returns a constant from the DayOfWeek enum whose toString method gives us a nice readable string such as MONDAY, again in contrast to what we get from Calendar.
public static String findDay(int month, int day, int year) {
Calendar cal = Calendar.getInstance();
cal.set(year, (month - 1), day);
String dayOfWeek = cal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault());
return dayOfWeek.toUpperCase();
}
Formatting data and time using java.util date and calendar as follows, where it needed to handle an exception with java.text.SimpleDateFormat in java 7.
public static void main(String[] args){
String inputDateStr = String.format("%s/%s/%s", 23, 04, 1995);
Date inputDate = null;
try {
inputDate = new SimpleDateFormat("dd/MM/yyyy").parse(inputDateStr);
} catch (ParseException ex) {
Logger.getLogger(JavaApplication28.class.getName()).log(Level.SEVERE, null, ex);
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(inputDate);
String dayOfWeek = calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US).toUpperCase();
System.out.println(dayOfWeek);
}
Formatting date and time using java.time classes in java 8 as follows and it is immutable and thread-safe.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
LocalDateTime dateObj = LocalDateTime.now();
System.out.println("Before formatting: " + dateObj);
DateTimeFormatter formatObj = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
String formattedDate = dateObj.format(formatObj);
System.out.println("After formatting: " + formattedDate);
}
}

Generating all days between 2 given dates in Java [duplicate]

This question already has answers here:
how to get a list of dates between two dates in java
(23 answers)
Closed 6 years ago.
I'm trying to get an array of Dates, while my input is a 'from'/'to' structure.
So my input is:
String date1 = "2014-01-01";
String date2 = "2014-05-01";
My output should be an Arraylist with all dates between date1 and date2.
I've already looked for this, but I could only find questions about the difference between 2 dates:
SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";
try {
Date date1 = myFormat.parse(inputString1);
Date date2 = myFormat.parse(inputString2);
long diff = date2.getTime() - date1.getTime();
System.out.println ("Days: " + TimeUnit.DAYS.convert(diff,TimeUnit.MILLISECONDS));
} catch (ParseException e) {
e.printStackTrace();
}
Any hints or suggestions? All other questions are for iOS or SQL.
Take a look at JodaTime: http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html
DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);
List<Date> allDates = new ArrayList();
while( dateTime1.before(dateTime2) ){
allDates.add( dateTime1.toDate() );
dateTime1 = dateTime1.plusDays(1);
}
Below is the code to get array of dates between the two string date.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
public class DateFormatExample {
public static void main(String[] args) {
// TODO Auto-generated method stub
SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String date1 = "2014-01-01";
String date2 = "2014-05-01";
try {
Date d1 = myFormat.parse(date1);
Date d2 = myFormat.parse(date2);
List<Date> allDates = new ArrayList<Date>();
List<String> allDatesString = new ArrayList<String>();
while( d1.before(d2) ){
d1 = addDays(d1, 1);
allDates.add(d1);
allDatesString.add(formatter.format(d1));
}
System.out.println(allDates);
System.out.println(allDatesString);
} catch (ParseException e) {
e.printStackTrace();
}
}
private static Date addDays(Date d1, int i) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(d1);
cal.add(Calendar.DATE, 1);
return cal.getTime();
}
}
If you don't want to use third party libraries you can use Calendar:
Check here a working demo.
public static void main(String[] args) throws Exception {
SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";
ArrayList<Date> dates = new ArrayList<Date>();
try {
Date date1 = myFormat.parse(inputString1);
Calendar c1 = DateToCalendar(date1);
Date date2 = myFormat.parse(inputString2);
Calendar c2 = DateToCalendar(date2);
while (!areEqualDate(c1, c2)) {
dates.add(c1.getTime());
System.out.println (c1.getTime());
c1.add(Calendar.DAY_OF_YEAR, 1);
}
} catch (ParseException e) {
e.printStackTrace();
}
// ArrayList<Date> dates >> contain all dates between both given days.
}
private static boolean areEqualDate(Calendar c1, Calendar c2) {
if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR)) return false;
if (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH)) return false;
if (c1.get(Calendar.DAY_OF_YEAR) != c2.get(Calendar.DAY_OF_YEAR)) return false;
return true;
}
public static Calendar DateToCalendar(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
}
I like JodaTime, but this can also be done without 3rd party libraries by using java.util.Calendar. Given a Calendar object, one can use its add method to increase certain fields of the date while honoring the calendar rules (like adding 1 day to the 31st of January gets you to the 1st of February, not to the 32nd of January).
First get the dates into one Calendar object each, in the correct chronological order so adding is going in the right direction later:
Calendar cStart = Calendar.getInstance(),
cStop = Calendar.getInstance();
if (date1.before(date2)) {
cStart.setTime(date1);
cStop.setTime(date2);
} else {
cStart.setTime(date2);
cStop.setTime(date1);
date1 and date2 are the parsed Date objects from your question, for simplicity's sake.
Next, loop over an "add 1 to day-of-year" instruction until this gets you beyond the stop date:
do {
System.out.println(pretty(cStart));
cStart.add(Calendar.DAY_OF_YEAR, 1);
} while (cStart.before(cStop));
And lastly print the stop date
System.out.println(pretty(cStop));
pretty() is just some mini method sending the calendar through a SDF, like the one you used for parsing the Strings in the first place.
This solution will print the date range, including the start and stop dates, and might need some tweaking around the edge cases (like date1==date2). Can be easily adapted to exclude the start and stop dates. Printing can be swapped for aggregation of course. To get a Date object from the calendar, use the getTime() method (returns a snapshot, not a live reference).
The documentation for the relevant (Gregorian)Calendar can be found here.
In case you are using Guava, there is a very elegant solution to this problem.
Guava has two neat classes, such as Range and ContiguousSet, which implement exactly what you need: first one operates on ranges of values, and second one - is able to convert a range to a set of discrete values.
Example of usage of both (together with JodaTime):
LocalDate start = LocalDate.parse("2015-01-01");
LocalDate end = LocalDate.parse("2019-02-01");
Range<LocalDate> range = Range.closed(start, end); //Creates a "closed" range, that is both dates are inclusive. There are also options like "openClosed", "closedOpen" and "open"
final Set<LocalDate> daySet = ContiguousSet.create(range, LocalDateDomain.INSTANCE); //Create a "virtual" set of days in given the range. "virtual" part means that if you create a set of 10 thousand years, it will not eat your memory at all
for (LocalDate day : daySet) {
//...operation...
}
Personally, I really prefer this way, as it eliminates some problems with understanding closed/open ranges, and makes code much easier to read and understand, while making no impact on performance. Also, it works with any kinds of dates, any libraries (you can swap YodaTime to Java8 Dates or even Java7- Date-based implementation).
Moreover, it allows you to do some neat operations on ranges like intersections, unions, spanning of ranges, incredibly fast "contains" and so on.
Only downsides are:
Dependence on Guava.
Need to create a special "DiscreteDomain" class, which Guava uses to understand where one date ends and other begins.
Example of LocalDateDomain implementation which operates as a bridge between Guava and JodaTime:
public class LocalDateDomain extends DiscreteDomain<LocalDate> {
public static final LocalDateDomain INSTANCE = new LocalDateDomain();
#Override
public LocalDate next(LocalDate value) {
return value.plusDays(1);
}
#Override
public LocalDate previous(LocalDate value) {
return value.minusDays(1);
}
#Override
public long distance(LocalDate start, LocalDate end) {
return Days.daysBetween(start, end).getDays();
}
}
I already know that OP isn't using Java 8 but here's the current solution - Java has been revamped and the new java.time API does every conceivable job in that regard:
//change these values :
LocalDate ld1 = LocalDate.ofEpochDay(0);
LocalDate ld2 = LocalDate.now();
//do NOT change these:
final LocalDate begin = ld1.isBefore(ld2) ? ld1 : ld2;
final LocalDate end = ld2.isAfter(ld1) ? ld2 : ld1;
for (int i = 0; i < begin.until(end, ChronoUnit.DAYS); i++) {
final LocalDate curDate = begin.plusDays(i);
System.out.println("current date : " + curDate);
}
This will output every valid day between the two dates whereas most of the other solutions will also give you invalid ones; heres the thing: temporal calculations need to be done on timezone-independent data - the output on the other hand may very well be timezone and/or chronology -dependent.
Thats why there are packages like java.time.format - simply calculate your time/date values and format them for your chosen region ... thats how its done correctly.
If you need to convert temporal input there are also useful functions in the time-API, i recommend doing a thorough tutorial on the subject, a few good introductions may be this and especially that :
There are two basic ways to represent time. One way represents time in
human terms, referred to as human time, such as year, month, day,
hour, minute and second. The other way, machine time, measures time
continuously along a timeline from an origin, called the epoch, in
nanosecond resolution. The Date-Time package provides a rich array of
classes for representing date and time. Some classes in the Date-Time
API are intended to represent machine time, and others are more suited
to representing human time.

Get month number from month name

I have this.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String monthName = br.readLine();
How to get month number which contain in monthName variable?
Thanks!
Use Java's Calendar class. It can parse any given string into a valid calendar instance.
Here is an example (assuming that the month is in english).
Date date = new SimpleDateFormat("MMMM", Locale.ENGLISH).parse(monthName);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
println(cal.get(Calendar.MONTH));
You can specify the language in SimpleDateFormat:
String monthName = "März"; // German for march
Date date = new SimpleDateFormat("MMMM", Locale.GERMAN).parse(monthName);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
println(cal.get(Calendar.MONTH));
By default, Java uses the user's local to parse the string.
Keep in mind that a computer starts counting at 0. So, January will be 0. If you want a human readable date, you should format the calendar instance:
SimpleDateFormat inputFormat = new SimpleDateFormat("MMMM");
Calendar cal = Calendar.getInstance();
cal.setTime(inputFormat.parse(monthName));
SimpleDateFormat outputFormat = new SimpleDateFormat("MM"); // 01-12
println(outputFormat.format(cal.getTime()));
Solution in Java 8 for English month names.
private int getMonthNumber(String monthName) {
return Month.valueOf(monthName.toUpperCase()).getValue();
}
Another approach using java.text.DateFormatSymbols is this:
public static int monthAsNumber(
String month,
Locale locale,
boolean abbreviated,
boolean caseInsensitive
) {
DateFormatSymbols dfs = new DateFormatSymbols(locale);
String[] months = (abbreviated ? dfs.getShortMonths() : dfs.getMonths());
if (caseInsensitive) {
for (int i = 0; i < 12; i++) {
if (months[i].equalsIgnoreCase(month)) {
return i; // month index is zero-based as usual in old JDK pre 8!
}
}
} else {
for (int i = 0; i < 12; i++) {
if (months[i].equals(month)) {
return i; // month index is zero-based as usual in old JDK pre 8!
}
}
}
return -1; // no match
}
The proposed signature of seach method illustrates the many possible variations. Example:
System.out.println(monthAsNumber("MÄRZ", Locale.GERMANY, false, true));
// output: 2 (zero-based!)
If you want a month number starting with 1 then just add 1 to the result (more intuitive and also my recommendation).
Starting with Java 8 you have a new variation, too, namely stand-alone months. While in English these month names are identical in other languages they are not always identical (for example in Czech language "leden" (January) instead of "ledna"). To achieve these stand-alone forms you can use Month.getDisplayName(...) (not tested):
public static int monthAsNumber(
String month,
Locale locale,
boolean abbreviated,
boolean caseInsensitive,
boolean standAlone
) {
TextStyle style;
Month[] months = Month.values[];
if (abbreviated) {
style = standAlone ? TextStyle.SHORT_STANDALONE : TextStyle.SHORT;
} else {
style = standAlone ? TextStyle.FULL_STANDALONE : TextStyle.FULL;
}
if (caseInsensitive) {
for (int i = 0; i < 12; i++) {
if (months[i].getDisplayName(style, locale).equalsIgnoreCase(month)) {
return i; // month index is zero-based as usual in old JDK pre 8!
}
}
} else {
for (int i = 0; i < 12; i++) {
if (months[i].getDisplayName(style, locale).equals(month)) {
return i; // month index is zero-based as usual in old JDK pre 8!
}
}
}
return -1; // no match
}
If you have month name and you want integer number corresponding to that month
try this
try{
Date date = new SimpleDateFormat("MMM", Locale.ENGLISH).parse(monthName);//put your month name in english here
Calendar cal = Calendar.getInstance();
cal.setTime(date);
monthNumber=cal.get(Calendar.MONTH);
System.out.println(monthNumber);
}
catch(Exception e)
{
e.printStackTrace();
}
Using Java 8 API
final DateTimeFormatter dtFormatter = DateTimeFormatter.ofPattern("MMM").withLocale(Locale.ENGLISH);
final TemporalAccessor temporalAccessor = dtFormatter.parse(month);
final int monthNumber = temporalAccessor.get(ChronoField.MONTH_OF_YEAR);
java.time
In March 2014, modern date-time API API supplanted the error-prone java.util date-time API and their formatting API, SimpleDateFormat. Since then it has been highly recommended to stop using the legacy API.
Solution using java.time, the modern Date-Time API:
Use a DateTimeFormatter with the pattern MMMM to parse the given date. If the name of the month can be in different cases, you should build and use a case-insensitive DateTimeFormatter.
Demo:
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
class Main {
public static void main(String[] args) {
// A sample month
String monthName = "March";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("MMMM", Locale.ENGLISH);
Month month = Month.from(parser.parse(monthName));
int monthNumber = month.getValue();
System.out.println(monthNumber);
// A case-insensitive formatter
DateTimeFormatter parserIgnoreCase = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("MMMM")
.toFormatter(Locale.ENGLISH);
System.out.println(Month.from(parserIgnoreCase.parse("march")).getValue());
}
}
Output:
3
3
Note: Never use SimpleDateFormat or DateTimeFormatter without a Locale.
Learn more about the modern Date-Time API from Trail: Date Time.

Categories

Resources