Using the Comparable interface to sort through dates - java

I'm trying to write a simple program that will sort the order of given dates, by sorting from earliest date to latest.
I'm able to sort the dates by their years, however when 2 dates have the same year and I need to sort by month, it starts having problems. I've been trying to nest if-statements and tried implementing while loops but I can't quite seem to get it right. I know that in my if statements, I'm missing some kind of statement that tells java to sort by month < other.month and day < other.day but I can't quite get it right...
Input/Output currently:
[10/5 1999, 19/5 1999, 10/3 1999, 19/3 1999, 10/5 2000, 19/5 2000, 10/3 2000, 19/3 2000]
[10/3 1999, 10/3 2000, 19/3 1999, 10/5 1999, 10/5 2000, 19/5 1999, 19/3 2000, 19/5 2000]
class Date implements Comparable<Date> {
private int year;
private int month;
private int day;
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
#Override
public int compareTo(Date other) {
if(year < other.year) {
return Integer.compare(this.year, other.year);
}
if(year == other.year) {
return Integer.compare(this.month, other.month);
}
if(month == other.month) {
return Integer.compare(this.day, other.day);
}
return day;
}
public String toString() {
return day + "/" + month + " " + year;
}
}

You're not checking all cases for years, year < other.year should be year != other.year In addition to that there's some other issues. What you want to be doing is:
if years aren't same
return sort by year
else, if months aren't same
return sort by months
else
return sort by days

Coding comparison for three fields is error-prone. To minimize the risk of bugs use the comparingInt and thenComparingInt methods of the Comparator interface, like Aomine already mentioned in a comment:
private static final Comparator<Date> dateComparator
= Comparator.comparingInt((Date d) -> d.year)
.thenComparingInt(d -> d.month)
.thenComparingInt(d -> d.day);
#Override
public int compareTo(Date other) {
return dateComparator.compare(this, other);
}
Even better, provide getters for the fields and use Date::getYear instead of (Date d) -> d.year and similarly for month and day.
The advantage is not so much that it’s shorter. The greatest advantage is it’s pretty hard to get wrong.

Related

Get the next valid date after a specified period has passed and adjust the day of month accordingly

I have an enum that looks like this
enum Period{DAY, WEEK, MONTH, YEAR}
What i need is a function that adds a specified amout of times the given Period to today while setting the day of month so that it is equal to the start date (if the outcome is valid).
Or maybe it is easier to understand like this:
Imagine you get your salary on the 31st every month (where applicable). The function returns the next valid date (from today) when you will receive your next salary. Where the function can distinguish if you get it Daily, Weekly, Monthly, Yearly and how often in the specified interval.
It also takes care of invalid dates
Lets have a look at an example:
public static Date getNextDate(Date startDate, Period period, int times){
/*
Examples:
getNextDate(31.08.2020, MONTH, 1) -> 30.09.2020
getNextDate(31.08.2020, MONTH, 2) -> 31.10.2020
getNextDate(30.05.2020, MONTH, 2) -> 30.09.2020
getNextDate(30.06.2020, MONTH, 2) -> 30.10.2020 (This is the next valid date after today)
Years are pretty simple i guess (Okay, there is at least one edge case):
getNextDate(28.02.2020, YEAR, 1) -> 28.02.2021
getNextDate(29.02.2020, YEAR, 1) -> 28.02.2021 <- Edge case, as 2020 is a gap year
getNextDate(29.02.2020, YEAR, 4) -> 29.02.2024 <- gap year to gap year
For weeks and days there are no edge cases, are there?
getNextDate(29.02.2020, DAY, 1) -> 03.09.2020
getNextDate(29.02.2020, DAY, 3) -> 05.09.2020
getNextDate(29.02.2020, WEEK, 2) -> 12.09.2020 (Same as DAY,14)
Important: If today is already a payment day, this already is the solution
getNextDate(03.09.2020, MONTH, 1) -> 03.09.2020 (No change here, the date matches today)
*/
}
I actually would prefer to use the modern LocalDate API (Just the input is an old date object at the moment, but will be changed later)
I hope i did not forget any edge cases.
Update with what i did
//This is a method of the enum mentioned
public Date getNextDate(Date baseDate, int specific) {
Date result = null;
switch (this) {
case DAY:
result = DateTimeUtils.addDays(baseDate, specific);
break;
case WEEK:
result = DateTimeUtils.addWeeks(baseDate, specific);
break;
case MONTH:
result = DateTimeUtils.addMonths(baseDate, specific);
break;
case YEAR:
result = DateTimeUtils.addYears(baseDate, specific);
break;
}
return result;
}
public Date getNextDateAfterToday(Date baseDate) {
today = new Date();
while(!baseDate.equals(today ) && !baseDate.after(today)){
baseDate= getNextDate(baseDate,1);
}
return startHere;
}
My getNextDate() Method works. The getNextDateAfterToday() also works, but does not return valid dates for edge cases. Example 31.06.2020, MONTH,1 would immediatly be stuc at 30st of every month and never skip back even if the month has 31 days. For 30.09.2020 it would be correct. But for 31.10.2020 it wouldn't
I finally figured a way (although it seems way, way, way to complicated for what i really wanted to achieve). I changed my getNextDateAfterTodayto this
public Date getNextValidFutureDate(Date entryDate, Date startDate, int specific) {
Date result = new Date(startDate.getTime());
while (!result.equals(entryDate) && !result.after(entryDate)) {
result = getNextDate(result, true, specific);
}
LocalDate ldStart = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate ldResult = result.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
if (ldResult.getDayOfMonth() < ldStart.getDayOfMonth() && this != DAY && this != WEEK && this != YEAR) {
if (ldResult.lengthOfMonth() >= ldStart.getDayOfMonth()) {
ldResult = ldResult.with(ChronoField.DAY_OF_MONTH, ldStart.getDayOfMonth());
} else {
ldResult = ldResult.with(ChronoField.DAY_OF_MONTH, ldResult.lengthOfMonth());
}
}
return Date.from(ldResult.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
I did not change the other method to use LocalDate, but will do this in the future.
This works with all test cases i posted above. Though i hope i did not miss essential ones
… (although it seems way, way, way to complicated for what i really
wanted to achieve) …
Your own solution is not bad. I just couldn’t let the challenge rest, so here’s my go. I believe it’s a little bit simpler.
I am going all-in on java.time, the modern Java date and time API. I also skipped your Period enum since the predefined ChronoUnit enum fulfils the purpose. Only it also includes hours, minutes and other units that don’t make sense here, so we need to reject those.
The Date class is poorly designed as well as long outdated. Avoid it if you can (if you cannot avoid it, I am giving you the solution in the end).
public static LocalDate getNextDate(LocalDate startDate, TemporalUnit period, int times) {
if (! period.isDateBased()) {
throw new IllegalArgumentException("Cannot add " + period + " to a date");
}
LocalDate today = LocalDate.now(ZoneId.of("America/Eirunepe"));
if (startDate.isBefore(today)) {
// Calculate how many times we need to add times units to get a future date (or today).
// We need to round up; the trick for doing so is count until yesterday and add 1.
LocalDate yesterday = today.minusDays(1);
long timesToAdd = period.between(startDate, yesterday) / times + 1;
return startDate.plus(timesToAdd * times, period);
} else {
return startDate;
}
}
For demonstrating the method I am using this little utility method:
public static void demo(LocalDate startDate, TemporalUnit period, int times) {
LocalDate nextDate = getNextDate(startDate, period, times);
System.out.format("getNextDate(%s, %s, %d) -> %s%n", startDate, period, times, nextDate);
}
Now let’s see:
demo(LocalDate.of(2020, Month.AUGUST, 31), ChronoUnit.MONTHS, 1);
demo(LocalDate.of(2020, Month.AUGUST, 31), ChronoUnit.MONTHS, 2);
demo(LocalDate.of(2020, Month.MAY, 30), ChronoUnit.MONTHS, 2);
demo(LocalDate.of(2020, Month.JUNE, 30), ChronoUnit.MONTHS, 2);
System.out.println();
demo(LocalDate.of(2020, Month.FEBRUARY, 28), ChronoUnit.YEARS, 1);
demo(LocalDate.of(2020, Month.FEBRUARY, 29), ChronoUnit.YEARS, 1);
demo(LocalDate.of(2020, Month.FEBRUARY, 29), ChronoUnit.YEARS, 4);
System.out.println();
demo(LocalDate.of(2020, Month.FEBRUARY, 29), ChronoUnit.DAYS, 1);
demo(LocalDate.of(2020, Month.FEBRUARY, 29), ChronoUnit.DAYS, 3);
demo(LocalDate.of(2020, Month.FEBRUARY, 29), ChronoUnit.WEEKS, 2);
System.out.println();
demo(LocalDate.of(2020, Month.SEPTEMBER, 4), ChronoUnit.MONTHS, 1);
When running just now, the output was:
getNextDate(2020-08-31, Months, 1) -> 2020-09-30
getNextDate(2020-08-31, Months, 2) -> 2020-10-31
getNextDate(2020-05-30, Months, 2) -> 2020-09-30
getNextDate(2020-06-30, Months, 2) -> 2020-10-30
getNextDate(2020-02-28, Years, 1) -> 2021-02-28
getNextDate(2020-02-29, Years, 1) -> 2021-02-28
getNextDate(2020-02-29, Years, 4) -> 2024-02-29
getNextDate(2020-02-29, Days, 1) -> 2020-09-04
getNextDate(2020-02-29, Days, 3) -> 2020-09-05
getNextDate(2020-02-29, Weeks, 2) -> 2020-09-12
getNextDate(2020-09-04, Months, 1) -> 2020-09-04
I should say that it agrees with your examples from the question.
If you cannot avoid having an old-fashioned Date object and an instance of your own Period enum and/or you indispensably need an old-fashioned Date back, you may wrap my method into one that performs the necessary conversions. First I would extend your enum to know its corresponding ChronoUnit constants:
enum Period {
DAY(ChronoUnit.DAYS),
WEEK(ChronoUnit.WEEKS),
MONTH(ChronoUnit.MONTHS),
YEAR(ChronoUnit.YEARS);
private final ChronoUnit unit;
private Period(ChronoUnit unit) {
this.unit = unit;
}
public ChronoUnit getUnit() {
return unit;
}
}
Now a wrapper method may look like this;
public static Date getNextDate(Date startDate, Period period, int times) {
ZoneId zone = ZoneId.of("America/Eirunepe");
LocalDate startLocalDate = startDate.toInstant().atZone(zone).toLocalDate();
LocalDate nextDate = getNextDate(startLocalDate, period.getUnit(), times);
Instant startOfDay = nextDate.atStartOfDay(zone).toInstant();
return Date.from(startOfDay);
}
Not using the decade old date api which is badly written and generally unsafe and painful to use might be the best idea. Using java.time might be in your favor here. Changing your method signature to this, is all you'd have to do:
import java.time.LocalDate;
import java.time.Period;
...
public static LocalDate getNextDate(LocalDate startDate, Period period) {
return startDate.plus(period);
}
And can then be called like:
LocalDate startDate = LocalDate.of(3, 9, 2020);
LocalDate nextDate = getNextDate(startDate, Period.ofDays(20)); // 2020-09-23
Or simply dropping your helper function in the first place and using it directly:
LocalDate nextDate = startDate.plus(Period.ofDays(20));
You can use the class Calendar to resolve your problem like that :
public static Date getNextDate(Date startDate, int period, int times) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
calendar.add(period, times);
return calendar.getTime();
}
The period is an int defined in the Calendar class, you can call your function like that :
System.out.println(getNextDate(new Date(), Calendar.MONTH, 1));
System.out.println(getNextDate(new Date(), Calendar.MONTH, 3));
System.out.println(getNextDate(new Date(), Calendar.YEAR, 1));
If you realy need to use your enum, you can do it !

Java Constructor date set

how to set DATE using constructor?
public Date(int day, int month, int year)
{
this.day=day; // set day to 1-31
this.month=month; // set month to 1-12
this.year=year; // set year to 1900-9999
}
if i use
if(day<=1 || day >=31)
this.day=day;
else if(month<=1 || month>=12)
this.month=month;
else if(year<=1900 || year>=9999)
this.year=year
the problem is if I do this it will only result to 0 however if I removed the conditional statements the day will accept until 32 and months will be accept 13 up and so on
Well, you tell me. What do you want to happen? Here are some common options:
(recommended): Decree that a given date that clearly cannot exist, is not a legal invocation of the constructor. In other words, new Date(32, 2, 2051) isn't valid. To do that, throw an exception. For example:
if (day > 31) throw new IllegalArgumentException("Days must be between 1 and 31, inclusive");
Use rollover behaviour, and round off years. This is a 'I don't care it makes no sense do SOMETHING and just don't crash' attitude, and is not recommended. For example, you'd make that date as above act like march 4th, 2051.
Something else of your choosing. You are the programmer, after all.
Note that you are reinventing a very common wheel, and thus, unless this is homework or a pure learning exercise ('pure' in the sense of: This code will be tossed in the garbage once you have completed it), it is a mistake. use LocalDate instead.
NB: Dates are HARD. Harder than you think.
You don't have to create date attributes for holding date information. You can just use either java 8 LocalDate or Date API . LocalDate is thread safe and immutable, most recommended way of handling date use cases.
If you insist on creating your own Date class you can just easily do the following.
import java.time.*;
public class Date {
final LocalDate date;
public Date(int day, int month, int year) {
date = LocalDate.of(year, month, day);
}
public int getYear() {
return date.getYear();
}
public Month getMonth() {
return date.getMonth();
}
public int getDay() {
return date.getDayOfMonth();
}
}
Using the Date class.
public class Main {
public static void main(String[] args) {
try{
Date date1 = new Date(2020, 13, 33);
} catch(DateTimeException ex){
System.out.println("Invalid input");
}
}
}

java: represent Date with optional month and day

I would like to store Date with optional month and day in java.
I know of the java.time.LocalYear to store just the year.
Shall I create my own custom class to hold dates with optional month and day or are there any custom library to solve the problem.
public class Date {
private LocalYear year;
private int month;
private int day;
public Date(LocalYear year) {
this.year = year;
}
public Date(LocalYear year, int month) {
this.year = year;
this.month = month;
}
public Date(LocalYear year, int month, iny day) {
this.year = year;
this.month = month;
this.day = day;
}
}
It’s hard to guide you without knowing your use case. One option is using the TemporalAccessor interface as a common type for dates with and without month and/or day of month and then put either a LocalDate, a YearMonth or a Year into your variable (the last class is just called Year (not LocalYear, though it would have been in line with the naming scheme)). For example:
List<TemporalAccessor> dates = List.of(
LocalDate.of(2019, Month.OCTOBER, 3), // full date
YearMonth.of(2019, Month.NOVEMBER), // no day of month
Year.of(2020)); // no month or day of month
What can we use this for? One example:
for (TemporalAccessor ta : dates) {
System.out.println(ta);
System.out.println("Year: " + ta.get(ChronoField.YEAR));
if (ta.isSupported(ChronoField.MONTH_OF_YEAR)) {
System.out.println("Month: " + ta.get(ChronoField.MONTH_OF_YEAR));
} else {
System.out.println("Month: undefined");
}
if (ta.isSupported(ChronoField.DAY_OF_MONTH)) {
System.out.println("Day: " + ta.get(ChronoField.DAY_OF_MONTH));
} else {
System.out.println("Day: undefined");
}
System.out.println();
}
This outputs:
2019-10-03
Year: 2019
Month: 10
Day: 3
2019-11
Year: 2019
Month: 11
Day: undefined
2020
Year: 2020
Month: undefined
Day: undefined
Whether or how well it fulfils your requirements I cannot tell.
Using ChronoField constants for access is low-level, so you may want to wrap the TemporalAccessor in a nice class with nice getters. For example:
public class PartialDate {
private TemporalAccessor date;
public PartialDate(Year year) {
date = year;
}
public PartialDate(Year year, int month) {
date = year.atMonth(month);
}
public PartialDate(Year year, int month, int day) {
date = year.atMonth(month).atDay(day);
}
public Year getYear() {
return Year.from(date);
}
public OptionalInt getMonthValue() {
if (date.isSupported(ChronoField.MONTH_OF_YEAR)) {
return OptionalInt.of(date.get(ChronoField.MONTH_OF_YEAR));
} else {
return OptionalInt.empty();
}
}
// A similar getDay method
}
You may extend the class to your needs. Maybe you want constructors that accept a Month enum constant and/or a YearMonth object directly and/or getters that return those types wrapped in Optionals.
Link: Oracle tutorial: Date Time explaining how to use java.time.

Java get the date X days later

I am setting up a db40 database, and it is filled with instances of my class Day() which has sales information for that day in history, and an integer for its ID.
The id is formatted like so: YYYYMMDD, so that they are all unique. My db is set up with the correct data chronologically, but right now I am forced to go in and edit the id's manually for over a year's worth of data.
Question: assuming day 1 is January 1, 2014 which would be formatted: 20140101, how do I correctly increment the date by one day each time? I have 424 dates I need to calculate after that, but I can't think of a clever solution without brute forcing it.
So ideally, i would want something like this getDate(ThisDate+1 Day)
As you're using Java 8, I'd use java.time for this:
Convert the integer (ick) into a LocalDate
Add however many days you want
Convert back to an integer (ick)
So something like:
static LocalDate dateFromId(int id) {
int year = id / 10000;
int month = (id / 100) % 100;
int day = id % 100;
return LocalDate.of(year, month, day);
}
static int idFromDate(LocalDate date) {
return date.getYear * 10000
+ date.getMonthValue() * 100
+ date.getDayOfMonth();
}
static int advanceId(int id, int days) {
LocalDate original = dateFromId(id);
LocalDate advanced = original.plusDays(days);
return idFromDate(advanced);
}
Or to compute a bunch of them:
LocalDate original = dateFromId(id);
for (int i = 1; i <= count; i++) {
LocalDate advanced = original.plusDays(i);
int advancedId = idFromDate(advanced);
// Use advanced
}

How can I return int date,month, year in a single method

I have written a java program which will return date, month and year
(datatype int)
import java.util.*;
class DateTime {
int day,month,year;
GregorianCalendar date = new GregorianCalendar();
public DateTime () {
public int TimeT() {
day = date.get(Calendar.DAY_OF_MONTH);
month = date.get(Calendar.MONTH);
year = date.get(Calendar.YEAR);
// return day;
}
}
I am really confuse how to return day, month and year.
I have to return it, so I can use it many times.
Define a type to encapsulate the three attributes, and change method return type to that class, like this:
public class YearMonthDay {
private final year;
private final month;
private final day;
public int getYear() {return year;}
public int getMonth() {return month;}
public int getDay() {return day;}
public YearMonthDay(int y, int m, int d) {
year = y;
month = m;
day = d;
}
// Consider overriding toString, and optionally hashCode and equals
}
Now you can change your class to return YearMonthDay:
public YearMonthDay TimeT(){
return new YearMonthDay(
date.get(Calendar.YEAR)
, date.get(Calendar.MONTH)
, date.get(Calendar.DAY_OF_MONTH)
);
}
A caller can now obtain the YearMonthDay once, and then access its properties from multiple places.
I think I may see what you are trying to say. 'Braj' had the right idea in the code he offered. However, I am not sure if that fully answers your needs or not. I am unsure as to whether you want to return each value (day, month, year) separately, or all together using one method? I will try my best regardless.
Below I will show you the code for DateTime:
import java.util.GregorianCalendar;
class DateTime {
private int day, month, year;
GregorianCalendar date = new GregorianCalendar();
public DateTime() {
day = date.get(GregorianCalendar.DAY_OF_MONTH);
month = date.get(GregorianCalendar.MONTH) + 1;
year = date.get(GregorianCalendar.YEAR);
}
public DateTime(int day, int month, int year){
this.day = day;
this.month = month;
this.year = year;
}
// Accessors ///
public int getDay(){
return day;
}
public int getMonth(){
return month;
}
public int getYear(){
return year;
}
// Mutators ///
public int setDay(){
return day;
}
public int setMonth(){
return month;
}
public int setYear(){
return year;
}
// String ///
public String toString(){
return getMonth() + "/" + getDay() + "/" + getYear();
}
}
Now to explain.
I made the day, month, and year private to begin with and kept your default constructor practically the same except for one thing.
I added 1 to the month because months January - December are indexed at 0 - 11 rather than 1 - 12. This means your month wouldn't follow conventional means. I never knew something such as the GregorianCalendar existed in java's import libraries, so I was initially confused for a couple of seconds when I tested my code.
Moving on I made an additional constructor in case you ever wanted to input your own dates for whatever reason. If you do not plan on making separate DateTime objects to hold random dates, then this is completely unnecessary.
Afterwards I made several accessors - getDay(), getMonth(), getYear() - in case you ever needed to grab the specific aspect of the date.
To finish it off I made a toString() method to print out your DateTime's day month and year all in one String in a conventional format.
If you don't want to change the individual aspects of the date (such as the day, the month, or the year) I'd recommend getting rid of the 'Mutators'. If you don't want to access the individual aspects of the date, then I'd recommend getting rid of the 'Accessors'.
NOW, if for some reason, you want to be able to edit and access the date's components inside your CLIENT, then you should not make the instances of day, month, and year private, but instead public.
Here is the code for the DateTime class that will allow you to change the values inside the CLIENT. (I don't recommend this. I suggest you get used to making accessors and mutators instead.) I decided to call it DateTime2:
import java.util.GregorianCalendar;
class DateTime2 {
public int day, month, year;
GregorianCalendar date = new GregorianCalendar();
public DateTime2() {
day = date.get(GregorianCalendar.DAY_OF_MONTH);
month = date.get(GregorianCalendar.MONTH) + 1;
year = date.get(GregorianCalendar.YEAR);
}
public DateTime2(int day, int month, int year){
this.day = day;
this.month = month;
this.year = year;
}
public String toString(){
return month + "/" + day + "/" + year;
}
}
I left the second constructor in there in case you still want to make separate DateTime2 objects with different dates...
And here if the client code that tests the two classes out, followed by the output:
CLIENT:
public class DateTime_CLIENT{
public static void main(){
DateTime dt = new DateTime();
System.out.println("- DateTime -");
System.out.println("Date: " + dt);
System.out.println("Month: " + dt.getMonth());
System.out.println("Day: " + dt.getDay());
System.out.println("Year: " + dt.getYear() + "\n");
DateTime2 dt2 = new DateTime2();
System.out.println("- DateTime2 -");
System.out.println("Date: " + dt2);
System.out.println("Month: " + dt2.month);
System.out.println("Day: " + dt2.day);
System.out.println("Year: " + dt2.year + "\n");
dt2.day = 400000;
System.out.println("- DateTime2 - CHANGE FROM CLIENT");
System.out.println("Date: " + dt2);
System.out.println("Month: " + dt2.month);
System.out.println("Day: " + dt2.day);
System.out.print("Year: " + dt2.year);
}
}
OUTPUT:
- DateTime -
Date: 7/16/2014
Month: 7
Day: 16
Year: 2014
- DateTime2 -
Date: 7/16/2014
Month: 7
Day: 16
Year: 2014
- DateTime2 - CHANGE FROM CLIENT
Date: 7/400000/2014
Month: 7
Day: 400000
Year: 2014
Hope this helped! ;D
Create different method for each one
public int getDay(Date date){
return date.get(Calendar.DAY_OF_MONTH);
}
public int getMonth(Date date){
return date.get(Calendar.MONTH);
}
public int getYear(Date date){
return date.get(Calendar.YEAR);
}
Create a class out of the three fields and return an object of this type.
Java can't actually return multiple values with a method. However, you can have your method return a string with the necessary information, then parse the string. Alternatively, create a daymonthyear object with all of the necessary attributes and return the object.
Use a HashMap:
public HashMap<String, Integer> TimeT() {
HashMap<String, Integer> dateMap = new HashMap<String, Integer>();
dateMap.put("day",date.get(Calendar.DAY_OF_MONTH));
dateMap.put("month",date.get(Calendar.MONTH));
dateMap.put("year",date.get(Calendar.YEAR));
return dateMap;
}
String In Standard Format, ISO 8601
If you want to return the date information as text, use the Joda-Time library or the new java.time package in Java 8 to convert a date-time value into a String using the format defined by the ISO 8601 standard.
Those two libraries use ISO 8601 format by default. Such as 2014-07-13T18:02:49+05:30:
String output = DateTime.now().toString(); // YYYY-MM-DDTHH:MM:SS.SSS+-00:00:00 format.
But it is best to specify a desired time zone rather than rely implicitly on the JVM's default time zone.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
String output = DateTime.now( timeZone ).toString();
If you want just year, month, and date only, then use an alternate formatter rather than the default one. The following code produces a string like 2014-07-13.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( timeZone );
DateTimeFormatter formatter = ISODateTimeFormat.date(); // YYYY-MM-DD formatter.
String output = formatter.print( now );
Pass DateTime Object
If instead of a string, you want the number values communicated to another object, then just pass the Joda-Time DateTime object. The receiving object can call methods on the DateTime such as getYear, getMonthOfYear, and getDayOfMonth. As a bonus, the receiving object will have additional information in its hands such as time zone.
The other answers are correct for the general case: Create a class or use a Collection to communicate multiple values as Java can return only a single item from a method. But in the specific case of date-time values, it seems silly to invent a class when we already have such classes at our disposal.
Avoid java.Util.Date and .Calendar
The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Using Joda-Time as a replacement is quite common. The new java.time package in Java 8 is another replacement, and was inspired by Joda-Time.
LocalDate Class
Both Joda-Time and java.time offer a LocalDate class to represent the date-only without time-of-day and without time zone. You may want to use this class. Usually a date-time is better if doing any comparisons across time zones, as a day’s beginning and ending are defined by a time zone.
Best case is make a class with members year, month and day, initialized in the method an returned.
If only and int have to be used you could merge the data with bit operations.
year | (month << 16) | (day << 24)
Don't known if it's valid java.
Reading would be:
year = date & 0xffff;
month = (date >> 16) & 0xff;
day = (date >> 24) & 0xff;
This is more common in native language.
It saems like the Calendar class already has everything the OP requires. There is no need to place the returned values into a hashmap or array or anything else. In the OP code, there is no return statement, but he wants to be able to re-use the code. Below is a simple method that demonstrates what the Calendar class gives us. Any method that returns a Calendar object is giving us everything we need because we can pull out the required values using get.
public static void main(String[] args) {
int day,month,year;
GregorianCalendar date = new GregorianCalendar();
day = date.get(Calendar.DAY_OF_MONTH);
month = date.get(Calendar.MONTH);
year = date.get(Calendar.YEAR);
System.out.println("Day:" + day);
System.out.println("month:" + month);
System.out.println("year:" + year);
}
Keep it simple. Return either the Date object (it contains everything you need) or an ISO string corresponding to this date in order to rebuild it later.

Categories

Resources