Narrow a Joda-Time partial - java

What's the best way to construct a partial from another partial which conains all the necessary fields (e.g. YearMonth from LocalDate? One way I can see is to convert to a full instant and back, that is
YearMonth ld2ym(LocalDate ld) {
return new YearMonth(ld.toDateTime(DateTime.now()));
}
but it seems like a more efficient way should be possible.

On the YearMonth class we can find this method which seems to give the appropriate solution:
/**
* Parses a {#code YearMonth} from the specified string using a formatter.
*
* #param str the string to parse, not null
* #param formatter the formatter to use, not null
* #since 2.0
*/
public static YearMonth parse(String str, DateTimeFormatter formatter) {
LocalDate date = formatter.parseLocalDate(str);
return new YearMonth(date.getYear(), date.getMonthOfYear());
}

Related

Java Custom Data Type

I wanted to create a class with a custom data type that returns the class object. Consider a class Custom:
public class Custom {
// Some fields.
public Custom(String custom) {
// Some Text.
}
// Some Methods.
public void customMethod() {
// Some Code.
}
}
Now, consider a second class TestCustom:
public class TestCustom {
public static void main(String[] args) {
Custom custom = new Custom("Custom");
System.out.println(custom); // This should print "Custom"
custom.customMethod(); // This should perform the action
}
}
So, the question how to get the value custom on instantiating an object instead of memory location. Like what I get is:
Custom#279f2327
The java.util.Date class returns the current date. This can be seen as the constructor for the class is
public Date() {
this(System.currentTimeMillis());
}
For example, the following code would print out the current date:
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date date = new Date();
System.out.println(format.format(date));
The Answer by ML72 is correct and should be accepted. The java.util.Date constructor captures the current moment in UTC.
java.time
The java.util.Date class is terrible, for many reasons. That class is now legacy, supplanted years ago but the java.time classes as of the adoption of JSR 310.
The java.time classes avoid constructors, instead using factory methods.
The replacement for java.util.Date is java.time.Instant. To capture the current moment in UTC, call the class method .now().
Instant instant = Instant.now() ;
If you want the current moment as seen through the wall-clock time used by the people of a particular region (a time zone), use ZoneId to get a ZonedDateTime object. Notice again the factory method rather than a constructor.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Adjust to UTC by extracting an Instant.
Instant instant = zdt.toInstant() ;
Override the toString() method, as it is automatically invoked when you try to display an object:
Add a field. For example;
private String value;
In the constructor, add the following code:
value = custom;
this will assign a value passed to the constructor as a parameter, to the value field.
And finally override the toString() method as follows:
#Override
public String toString() {
return value;
}
Now, when you display the value of the custom object, the overridden toString() method will be invoked and the argument will be displayed instead of the memory address. Whereas methods of the object will work as they are programmed to work. There is nothing to be changed with them.

Sort Array object by date of its field

I have an Object MyTimes and in that object there are fields name ,start_date and configuration.
I have an array of this object, MyTimes [] mytimes
I am trying to sort the array by the start time but am struggling how to go about it.
The start_time field is a string, so this needs converting to a datetime.
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
for(int i=0; i<mytimes.length; i++) {
Date date = formatter.parse(mytimes[i].getStartTime());
}
I'd then put the date into an array list perhaps and then sort by datetime? But then I wouldnt know which start_time corresponds with which mytimes object...
What is the most efficient way of doing this?
Under the right circumstances this is a one-liner:
Arrays.sort(myTimes, Comparator.comparing(MyTimes::getStartDate));
Let’s see it in action:
MyTimes[] myTimes = {
new MyTimes("Polly", "2019-03-06T17:00:00Z"),
new MyTimes("Margaret", "2019-03-08T09:00:00Z"),
new MyTimes("Jane", "2019-03-01T06:00:00Z")
};
Arrays.sort(myTimes, Comparator.comparing(MyTimes::getStartDate));
Arrays.stream(myTimes).forEach(System.out::println);
Output:
Jane 2019-03-01T06:00:00Z
Polly 2019-03-06T17:00:00Z
Margaret 2019-03-08T09:00:00Z
I am assuming that getStartDate returns an Instant or another type the natural order of which agrees with the chronological order you want. For example:
public class MyTimes {
private String name;
private Instant startDate;
// Constructor, getters, toString, etc.
}
If you are receiving your start dates as strings somehow, you may write a convenient constructor that accepts a string for start date. I am already using such a constructor in the above snippet. One possibility is having two constructors:
public MyTimes(String name, Instant startDate) {
this.name = name;
this.startDate = startDate;
}
public MyTimes(String name, String startDate) {
this(name, Instant.parse(startDate));
}
The Instant class is part of java.time, the modern Java date and time API.
I am exploiting the fact that your strings are in the ISO 8601 format for an instant, the format that Instant.parse accepts and parses.
Avoid SimpleDateFormat and Date
I recommend you don’t use SimpleDateFormat and Date. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. There is also an error in your format pattern string for parsing: Z (pronounced “Zulu”) means UTC, and of you don’t parse it as such, you will get incorrect times (on most JVMs). Instant.parse efficiently avoids any problems here.
Don’t store date-tine as a string
It looks like you are are storing start time in a String field in your object? That would be poor modelling. Use a proper date-time type. Strings are for interfaces. Date-time classes like Instant offer much more functionality, for example define sort order.
You have two main approaches:
Make your class implement Comparable
Use a custom Comparator
Then, you can choose the field to compare from, and transform it.
IE (implementing comparable):
class Example implements Comparable<Example> {
private String stringDate;
public int compareTo(Example e) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date date1 = formatter.parse(this.stringDate);
Date date2 = formatter.parse(e.stringDate);
return date1.getTime() - date2.getTime();
}
}
And then using Arrays.sort would use your custom comparison.
Let your class implement Comparable and implement compareTo using modern formatting and date classes. Note that LocalDateTime also implements Comparable so once the string has been parsed you let LocalDateTime do the comparison
public class MyTimes implements Comparable<MyTimes> {
private final DateTimeFormatter dtf = DateTimeFormatter.ISO_INSTANT;
//other code
public int compareTo(MyTimes o) {
LocalDateTime thisDate = LocalDateTime.from(dtf.parse(this.getStartTime()));
LocalDateTime otherDate = LocalDateTime.from(dtf.parse(o.getStartTime()));
return thisDate.compareTo(otherDate);
}
}
You can also create a separate class as a comparator if this comparison is special and what you not always want to use
public class MyTimesComparator implements Comparator<MyTimes> {
#Override
public int compare(MyTimes arg0, MyTimes arg1) {
DateTimeFormatter dtf = DateTimeFormatter.ISO_INSTANT;
LocalDateTime thisDate = LocalDateTime.from(dtf.parse(this.getStartTime()));
LocalDateTime otherDate = LocalDateTime.from(dtf.parse(o.getStartTime()));
return thisDate.compareTo(otherDate);
}
}
and then use it like
someList.sort(new MyTimesComparator());
or use an inline function (I am using Instant here)
someList.sort( (m1, m2) -> {
DateTimeFormatter dtf = DateTimeFormatter.ISO_INSTANT;
Instant instant1 = Instant.from(dtf.parse(m1.getStartTime));
Instant instant2 = Instant.from(dtf.parse(m2.getStartTime));
return intant1.compareTo(instant2);
});
I noticed now that you have an array and not a list so you need to convert to a list or use Arrays.sort instead.

How to enter a LocalDate value into BlueJ "Create Object" dialog box

I'm not trying to format the date in YYYY-MM-DD or dd/MM/YYYY. I'm asking about the literal format of LocalDate.
I just started learning Java and I am using this IDE called BlueJ. and I want to create a test method.
The screenshot will show what I am trying to do
Now since from the constructor we know that it requires a int, LocalDate and a double. I've searched online and found that
https://www.javabrahman.com/java-8/java-8-working-with-localdate-localtime-localdatetime-tutorial-with-examples/
java.time.LocalDate: A LocalDate instance holds a date without a time
zone, in ISO-86011 calendar system. LocalDate has the default format
‘YYYY-MM-DD’ as in ‘2016-12-12’.
So I would put a normal number in 10001 for the testID and double would be something like 50.5
I also know that for it to register a string (if it was needed) I would need to enclose it within "string"
But I've tried all sorts of way to put in the date and I would be left with an error
2018-05-30,30-05-2018,30/05/2018 would give me
Error: incompatible types: Int cannot be converted to java.time.LocalDate
"30/05/2018" on the other hand would give me
Error: Incompatible types: java.lang.String cannot be converted to java.time.LocalDate
If I try 30.05.2018 it would say
Error: ';' expected
If I try '2018-05-30' it would say
Error: unclosed character literal
I ran out of ways to try it. So if you could tell me how I should put it in there, that would be great.
I just really need to know how BlueJ wants me to input it. Cause the resources for BlueJ is so sparse online.
Code:
import java.time.LocalDate;
import java.util.ArrayList;
/**
* Write a description of class TestPaper here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class TestPaper
{
// instance variables - replace the example below with your own
private int testID;
private LocalDate testDate;
private double testMarks;
private ArrayList<MCQ> MCQDetails;
/**
* Constructor for objects of class TestPaper
*/
public TestPaper(int testID, LocalDate testDate, double testMarks)
{
this.testID = testID;
this.testDate = testDate;
this.testMarks = testMarks;
MCQDetails = new ArrayList<MCQ>() ;
}
/**
* Accessor Method getTestID to get the testID
*
* #return int value of the choice ID
*/
public int getTestID(){
return testID;
}
/**
* Mutator Method to set the testID
*
* #param int format of the testID to set
*/
public void setTestID(int testID){
this.testID = testID;
}
/**
* Accessor Method getTestMarks to get the Test Marks
*
* #return double value of the test marks
*/
public double getTestMarks(){
return testMarks;
}
/**
* Mutator Method to set the testMarks
*
* #param String format of the choice Description to be set
*/
public void setTestMarks(double testMarks){
this.testMarks = testMarks;
}
/**
* Accessor Method getTestDate to get the testDate
*
* #return LocalDate value of the testDate
*/
public LocalDate getTestDate(){
return testDate;
}
/**
* Mutator Method to set the testDate
*
* #param LocalDate format of the testDate to set
*/
public void setTestDate(LocalDate testDate){
this.testDate = testDate;
}
/**
* Method addMCQ will allow users to add a MCQ Object to the list of MCQ
*
* #param addMCQ a MCQ Object
* #return boolean will return true if it is successfully added or false if not
*/
public boolean addMCQ(MCQ MCQName)
{
return MCQDetails.add(MCQName);
}
/**
* Method removeMCQ to remove an MCQ object from the Arraylist
*
* #param MCQName A parameter of type MCQ
*/
public void removeMCQ(MCQ MCQName)
{
MCQDetails.remove(MCQName);
}
/**
* Method listMCQ to return a list of MCQ arraylist
*
* #return The return value of MCQDetails (MCQ Arraylist)
*/
public ArrayList<MCQ> listMCQ()
{
return MCQDetails;
}
public MCQ findMCQ(int MCQID)
{
for(MCQ m : MCQDetails)
{
if(m.getQuestionID() == MCQID)
{
return m;
}
}
return null;
}
Include package
As discussed in the comments, the solution is to add the code that creates the LocaDate, but bluej needs the fully qualified class name with the package prefix “java.time.”:
java.time.LocalDate.of(2018, 5, 30)
Not sure why it doesn't work with just LocalDate.of(...) (even with the class correclty imported), but at least this works.
Just another detail: a date has no format. Classes like LocalDate just holds values (in this case, it has year, month and day values), but a date itself has no format at all. The same date can be represented in many different formats: May 30th 2018, 2018-05-30, 30/05/18 are different formats, but all represent the same date. A date object just holds the values, and you can choose whatever format you want to represent it.
When you print a LocalDate, it implicity calls toString(), which by default chooses yyyy-MM-dd format, which is a ISO 8601 format, but as I said, that's just one of the many possible ways to format a date (although the value always stays the same). Telling that "a date has a format" is wrong and misleading.
Try converting the LocalDate in the call, such as:
TestPaper (2018-05-30, LocalDate.parse("2018/05/30"), 30/05/2018);
There are other static methods within LocalDate you can use. See here for more examples.
From your comment above, don't forget your import:
import java.time.LocalDate;

What is the format to add java Localdate parameters when creating objects in BlueJ [duplicate]

I'm not trying to format the date in YYYY-MM-DD or dd/MM/YYYY. I'm asking about the literal format of LocalDate.
I just started learning Java and I am using this IDE called BlueJ. and I want to create a test method.
The screenshot will show what I am trying to do
Now since from the constructor we know that it requires a int, LocalDate and a double. I've searched online and found that
https://www.javabrahman.com/java-8/java-8-working-with-localdate-localtime-localdatetime-tutorial-with-examples/
java.time.LocalDate: A LocalDate instance holds a date without a time
zone, in ISO-86011 calendar system. LocalDate has the default format
‘YYYY-MM-DD’ as in ‘2016-12-12’.
So I would put a normal number in 10001 for the testID and double would be something like 50.5
I also know that for it to register a string (if it was needed) I would need to enclose it within "string"
But I've tried all sorts of way to put in the date and I would be left with an error
2018-05-30,30-05-2018,30/05/2018 would give me
Error: incompatible types: Int cannot be converted to java.time.LocalDate
"30/05/2018" on the other hand would give me
Error: Incompatible types: java.lang.String cannot be converted to java.time.LocalDate
If I try 30.05.2018 it would say
Error: ';' expected
If I try '2018-05-30' it would say
Error: unclosed character literal
I ran out of ways to try it. So if you could tell me how I should put it in there, that would be great.
I just really need to know how BlueJ wants me to input it. Cause the resources for BlueJ is so sparse online.
Code:
import java.time.LocalDate;
import java.util.ArrayList;
/**
* Write a description of class TestPaper here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class TestPaper
{
// instance variables - replace the example below with your own
private int testID;
private LocalDate testDate;
private double testMarks;
private ArrayList<MCQ> MCQDetails;
/**
* Constructor for objects of class TestPaper
*/
public TestPaper(int testID, LocalDate testDate, double testMarks)
{
this.testID = testID;
this.testDate = testDate;
this.testMarks = testMarks;
MCQDetails = new ArrayList<MCQ>() ;
}
/**
* Accessor Method getTestID to get the testID
*
* #return int value of the choice ID
*/
public int getTestID(){
return testID;
}
/**
* Mutator Method to set the testID
*
* #param int format of the testID to set
*/
public void setTestID(int testID){
this.testID = testID;
}
/**
* Accessor Method getTestMarks to get the Test Marks
*
* #return double value of the test marks
*/
public double getTestMarks(){
return testMarks;
}
/**
* Mutator Method to set the testMarks
*
* #param String format of the choice Description to be set
*/
public void setTestMarks(double testMarks){
this.testMarks = testMarks;
}
/**
* Accessor Method getTestDate to get the testDate
*
* #return LocalDate value of the testDate
*/
public LocalDate getTestDate(){
return testDate;
}
/**
* Mutator Method to set the testDate
*
* #param LocalDate format of the testDate to set
*/
public void setTestDate(LocalDate testDate){
this.testDate = testDate;
}
/**
* Method addMCQ will allow users to add a MCQ Object to the list of MCQ
*
* #param addMCQ a MCQ Object
* #return boolean will return true if it is successfully added or false if not
*/
public boolean addMCQ(MCQ MCQName)
{
return MCQDetails.add(MCQName);
}
/**
* Method removeMCQ to remove an MCQ object from the Arraylist
*
* #param MCQName A parameter of type MCQ
*/
public void removeMCQ(MCQ MCQName)
{
MCQDetails.remove(MCQName);
}
/**
* Method listMCQ to return a list of MCQ arraylist
*
* #return The return value of MCQDetails (MCQ Arraylist)
*/
public ArrayList<MCQ> listMCQ()
{
return MCQDetails;
}
public MCQ findMCQ(int MCQID)
{
for(MCQ m : MCQDetails)
{
if(m.getQuestionID() == MCQID)
{
return m;
}
}
return null;
}
Include package
As discussed in the comments, the solution is to add the code that creates the LocaDate, but bluej needs the fully qualified class name with the package prefix “java.time.”:
java.time.LocalDate.of(2018, 5, 30)
Not sure why it doesn't work with just LocalDate.of(...) (even with the class correclty imported), but at least this works.
Just another detail: a date has no format. Classes like LocalDate just holds values (in this case, it has year, month and day values), but a date itself has no format at all. The same date can be represented in many different formats: May 30th 2018, 2018-05-30, 30/05/18 are different formats, but all represent the same date. A date object just holds the values, and you can choose whatever format you want to represent it.
When you print a LocalDate, it implicity calls toString(), which by default chooses yyyy-MM-dd format, which is a ISO 8601 format, but as I said, that's just one of the many possible ways to format a date (although the value always stays the same). Telling that "a date has a format" is wrong and misleading.
Try converting the LocalDate in the call, such as:
TestPaper (2018-05-30, LocalDate.parse("2018/05/30"), 30/05/2018);
There are other static methods within LocalDate you can use. See here for more examples.
From your comment above, don't forget your import:
import java.time.LocalDate;

Static Variables Not Affecting Other Objects in Java Calendar Class

Since the Calendar class in Java has static data fields such as DATE, why don't the other objects change when the static field is modified?
I have made two different Gregorian Calendars and thought static data fields changed the value for all of the objects instead of one.
import java.util.Calendar;
import java.util.GregorianCalendar;
public class TEST {
public static void main(String[] args) {
GregorianCalendar cal = new GregorianCalendar();
System.out.println(cal.get(Calendar.DATE));
GregorianCalendar cal2 = new GregorianCalendar();
cal2.set(Calendar.DATE, 12);
System.out.println(cal2.get(Calendar.DATE));
System.out.println(cal.get(Calendar.DATE));
}
}
Calendar.DATE is not a static field, it's a static variable that's used to reference which type of value you want to set/get in a specific Calendar instance.
If you look at the actual source code of java.util.Calendar you would see that it has an internal int array that holds all the values, i.e. day, month, year, etc.
Calendar.DATE is just a nice way of referencing the fifth element of that array.
Declaration of member in the Java 8 source code.
/**
* Field number for <code>get</code> and <code>set</code> indicating the
* day of the month. This is a synonym for <code>DAY_OF_MONTH</code>.
* The first day of the month has value 1.
*
* #see #DAY_OF_MONTH
*/
public final static int DATE = 5;
The Answer by rorschach is correct and should be accepted.
Also, you are using old date-time classes that have proven to be poorly designed, confusing, and troublesome. Avoid them. They have been supplanted by the java.time classes.
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate nextWeek = today.plusWeeks( 1 );
LocalDate midMonth = today.withDayOfMonth( 15 );
LocalDate firstOfMonth = today.with( TemporalAdjusters.firstDayOfMonth() );
LocalDate secondTuesdayOfThisMonth = today.with( TemporalAdjusters.dayOfWeekInMonth( 2 , DayOfWeek.TUESDAY ) );

Categories