I have a function that sometimes has to return a Date other times a DateTime (Joda-Time).
static public <T extends Object> T convertTimeForServer(DateTime toSave) {
DateTime temp = null;
try {
temp = toSave.withZone(DateTimeZone.forID(getServerTimeZone()));
} catch (Exception e) {
}
T toReturn = null;
if (toReturn.getClass().equals(temp)) {
return (T) temp;//Return DATETIME
} else {
return (T) temp.toDate();//Return DATE
}
}
Is it the right approach?
How to use it?
like this (timerHelper is the name of class):
DateTime t = timerHelper.<DateTime>convertTimeForServer(new DateTime());
Date t2 = timerHelper.<Date>convertTimeForServer(new DateTime());
or
DateTime t = (DateTime)timerHelper.convertTimeForServer(new DateTime());
Date t2 = (Date)timerHelper.convertTimeForServer(new DateTime());
And how to use this function instead?
static public <T extends Object> T current_Moment(){
return convertTimeForServer(new DateTime());
}
I suspect you're being too clever trying to use generics here. Because you don't have polymorphism on return types doesn't mean you should resort to generics to try and achieve that effect.
You can implement this simply as two methods: public static Date convertToDateForServer(DateTime toSave) {...} and public static DateTime convertToDateTimeForServer(DateTime toSave) {...}. The calling code seems to know what it wants, so it can simply call the method needed. If there really is a complex commonality to both methods, make a private method that both can call internally.
If Java 8 is available you could always implement an Either using the new Optional class.
This is one of the tricky areas of Generics. The only way to get this to work would be to take a Class argument, so the method knows what type of object to create. It can't know at the moment, because of Type Erasure.
Alternatively (much simpler) is to always return DateTime and do away with generics here.
The client will always know what it wants, and if the client wants a Date, it can create one from the DateTime far more easily than what you are trying to do.
Example:
Client 1 wants a DateTime:
DateTime result = service.convertTimeForServer(dt);
Client 2 wants a Date:
Date result = service.convertTimeForServer(dt).toDate();
Related
I've created my own MyDate class. It basically wraps a Long value with some pretty toString() functions. I've implemented equals() and compareTo(). my program reads some data and instantiates object of classes that hold this MyDate class. Problem is that sometimes that data is bad so I created a public static final long NODATE = Long.MIN_VALUE; so that I could initiate a new instance that is empty (replace the null in the containing class so to avoid NullPointerExceptions). I've also implemented a constructor with no arguments that inits the Long value to NODATE.
My Problem:
I want to check if a MyDate is valued as NODATE. I can't compare to NODATE since it's Long and not MyDate. One way to do this is:
if someObject.myDate.equals(new MyDate()).
But it seems like a waste to create an object just to make the comparison? Another way is to implement MyDate.amINoDate() method.
Is there another way? I was thinking of creating an static instance of MyDate that is inited to NODATE and to compare to it. But how can I compare my non static objects to this static object?
class MyDate {
public static final MyDate NODATE = new MyDate(Long.MIN_VALUE);
// ...
}
// ...
if (someDate.equals(MyDate.NODATE)) // ...
Thanks maskacovnik.
You can also add a method to MyDate like:
public boolean isNodate() {
return internalLongDate == Long.MIN_VALUE;
}
Add a method to MyDate:
if (someDate.isNoDate()) {
...
}
Also: personally I would avoid the Long.MIN_VALUE and use null.
I have a problem with the LSP in my program. I have a Base Class that is abstract and two different types of products , one is Food , the other is an Electronic device. I need to make a method that returns the expirationDate/Warranty for those products. The problem is that one is of type Date, and the other (warranty) is of type Int...
Do you have any idea how to make a method that satisfies both of those data types? without using switch/if statements since that will violate the OCP.
private static void printExpirationDateStatistics(List<Product> foodProducts) {
for (Product product : foodProducts) {
System.out.println(product.getExpirationDate());
}
}
Is there any way that is can modify this function to handle both food and electronics so I don't have to make another method for each new product is add ?
Those are the methods from the base class
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
public int getWarranty() {
return warranty;
}
public void setWarranty(int warranty) {
this.warranty = warranty;
}
I tried making one getValidity method but the problem is that for food it should return Date, and for electronics should return Int.
Any ideas ?
The problem you face here is that you want to abstract over two informationen a kind of common "expiration" information. The problem is that this abstraction is unknown to the code, it's currently only in present in your head :)
It's currently implemented in 2 flavours: Integers and Dates
(though I have no idea what this Integer is about? Is it a year count? ... the number of lottory winner since 1990? I don't know).
I would propose adding a new Interface for this abstraction, e.g.
public interface Expiration<T> {
T getExpiration();
}
In this case your two base classes can implement Expiration<Date> and Expiration<Integer> and you could base your validation logic on that. For example like:
public boolean isValid(Expiration<Date> potentialyExpired) {
final Date expirationDate = potentialyExpired.getExpiration();
final Date now = new Date();
return expirationDate.before(now);
}
That can only be done when you can access the classes in question though.
Is this abstraction enough or are you in need in even more?
You could want to abstract over the different type of Expiration in such a way that you don't need to have both of them around and unify them at some point. But to decide that kind of thing one would need to know more about the meaning of the other type (the Integer one).
Get / Set methods are there to protect my class fields.
But since Java is working with reference my private fields are still getting exposed..
e.g.
private Date d;
Date getDate(){
return d;
}
void setDate(Date inD){
//Checks for inD
d = inD;
}
//Still the issue is
getDate().setHours(xyz);
What is the correct approach? Because i dont want to change my Date without using setDate.
Because i dont want to change my Date without using setDate.
Then you shouldn't return a reference to a mutable object in your get method. For example:
private Date d;
Date getDate() {
// Return a reference to an independent copy of the original data
return new Date(d.getTime());
}
void setDate(Date inD) {
// Checks for inD
d = inD;
}
A better approach (IMO) would be to use immutable types for your fields - the Joda Time API is a much cleaner date/time library and it has plenty of immutable types.
Now that was just an example of course - in other cases you might want to return an immutable view on a mutable object (which you would usually avoid mutating yourself) in order to avoid having to copy a lot of data on each get call.
There is a good approach for that which is called Defensive Copy,
Date getDate(){
return new Date(d.getTime());
}
you'll get a copy of it and original one will have no affect
Date is just an abomination since it is mutable. What you could do to make it safe, is to return a copy of the date. If that is modified, the original value is not changed.
I have Date in this format 2009-09-17T00:00:00.000-35:00 . As per the business Rules for my Application , i have written 3 Methods which will accept this Date and returns the Date in MM/yyyy , yyyyMM and dd .
For example one method is shown below MM/yyyy
private String getMonthYear(String date) throws Exception {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
String s1 = date;
String s2 = null;
Date d;
try {
d = sdf.parse(s1);
s2 = (new SimpleDateFormat("MM/yyyy")).format(d);
} catch (ParseException e) {
e.printStackTrace();
}
return s2;
}
Similarly i have other two methods which will return data in yyyyMM and dd formats ??
This works fine , but does not look good
My question is can we have only one utility which satisfies my requirement ??
My question is can we have only one utility which satisfies my requirement ??
I think you're going about this the wrong way to start with. Fundamentally the data is just a date. You can apply formats later, when you need to. I suggest you start using Joda Time and make your method return a LocalDate. That captures all the real information, and you can then have three separate DateTimeFormatter objects used to format the value whenever you want.
Wherever you can, represent data using a type which most naturally represents the real information. Get your data into that natural format as early as possible, and keep it in that format until you have to convert it into something else (such as a string).
You could define a single method and receive as a parameter the string with the expected date format, the three strings with the formats could be defined as constants.
Yes, you could group the three methods together, and use an additional argument (an enum, for example) to specify which kind of output format you want. But I would not do that. Your solution is cleaner. Why do you think it doesn't look good?
What I would do, however, is transforming the String to a Date once and for all, and using a Date everywhere rather than the String, and transforming the Date with one of your 3 methods (which would take a Date as argument rather than a String) when needed.
The Apache Commons Lang library already has utility methods to do this for you.
For example:
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
///
// first, convert the string to a date object
Date parsedDate = DateUtils.parseDate("2012-05-25T16:10:30.000",
new String[] {"yyyy-MM-dd'T'HH:mm:ss.SSS"});
// now, format the date object to a string, using different formats
String formattedDate = DateFormatUtils.format(parsedDate, "MM/yyyy");
String formattedDate2 = DateFormatUtils.format(parsedDate, "yyyyMM");
Take a look at DateFormatUtils and DateUtils for more information.
You could just have a Date class which has the three methods. Like below:
public class MyDate {
private String date = null;
public MyDate(String date) {
this.date = date;
}
public String getMonthYear() {
return null;
}
public String getYearMonth() {
return null;
}
public String getDay() {
return null;
}
}
You can format the String into three different Strings in the constructor and just return those strings on method calls. That implementation would be good if you make numberous/repeated calls on the same date string. Or you could format the string in the method call, if you are doing it once but if you are doing it once you may want to make the class/methods static and get rid of the constructor.
I want a nice way to get the current unix timestamp from a java Date object, this is my solution:
public class Date extends java.util.Date {
public int getUnixTimeStamp() {
int unixtimestamp = (int) (this.getTime() * .001);
return unixtimestamp;
}
}
That works fine, but the problem is when I try to cast a java Date object to my custom date class, i.e:
Calendar foo = Calendar.getInstance();
foo.set(0, 0, 0, 12, 30);
myapp.Date foo2 = (myapp.Date)foo.getTime();
This generates: Exception in thread "main" java.lang.ClassCastException: java.util.Date cannot be cast to myapp.Date
I understand why this exception is made but is there any way to cast a superclass to a subclass? If not, how would you implement the unixtimestamp method? I use it quite often in my application.
You can't cast a superclass in a subclass because the subclass may have a bigger interface than the superclass means the subclass can have functions like getUnixTimeStamp() that the superclass doesn't have. In your example that would mean you trying to call getUnixTimeStamp on a java.util.Date.
You can use a Delegate or Composition instead of inheritance here.
That means you have a Class
public class Date {
private java.util.date date;
public Date(java.util.Date date) {
this.date = date
}
public int getUnixTimeStamp() {
int unixtimestamp = (int) ((this.date.getTime()) * .001);
return unixtimestamp;
}
}
In this way you don't cast the date into your date you create a class arround the java.util.date.
If you use only this function it could be an easier solution to just create a static util function getUnixTime(Date date) that returns the changed date.
If you're keen on having your subclass, implement a constructor in your Date class taking a java.util.Date foo and in it call super with foo.getTime(); then instead of casting you just call Date(foo) to instantiate your subclass.
Why do you need to make this class extend java.util.Date at all? Make a static function that takes a Date and returns the unix timestamp of that date.
As already mentioned you could implement it by letting the constructor of the class take the time as an input.
Something like this:
public class Date {
long unixtimestamp;
public Date(long time) {
unixtimestamp = (long) (time * .001);
}
public long getUnixTimeStamp() {
return unixtimestamp;
}
}
Another option is just to create a static method which converts it. It depends on whether you are planning on adding other similar features to the class or not. If not then a static-method is probably better.
No, you can't cast a type to a more derived type if the reference doesn't point to an instance of the derived type.
The Date being returned by Calendar.getTime() isn't one of your Date objects, and it doesn't have the additional attributes and behaviours those objects do.
You could modify your Date class to use composition instead of inheritance, e.g.
class Date {
private java.util.Date date;
public Date( java.util.Date date ) {
this.date = date;
}
public int getUnixTimestamp() {
return (int)( date.getTime() * .001 );
}
}