How to differentiate when "second field" is missing in LocalDateTime - time

I am given LocalDateTime object created from String. I want to check whether that original string has "seconds" parameter or not.
My two inputs are:
String a = "2016-06-22T10:01"; //not given
String b = "2016-06-22T10:01:00"; //not given
LocalDateTime dateA = LocalDateTime.parse(a, DateTimeFormatter.ISO_DATE_TIME);
LocalDateTime dateB = LocalDateTime.parse(b, DateTimeFormatter.ISO_DATE_TIME);
Problem is I am given dateA and dateB, not a and b.
I have tried various ways like converting LocalDateTime to String and finding its length. For that I used two approaches.
date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME).length();
date.toString().length();
But first approach gives length 19 for both dateA and dateB whereas second approach gives length 16 for both dateA and dateB.
I am unable to find any way to differentiate dateA and dateB.

As other people have already said, a LocalDateTime-object has always a second part. The other question is if the original input has got a second part or not. It is possible to find out the answer with only Java-8-means (but it is ugly because it is based on exception control flow):
String a = "2016-06-22T10:01"; // not given
String b = "2016-06-22T10:01:00"; // given
boolean hasSecondPart;
try {
TemporalAccessor tacc =
DateTimeFormatter.ISO_DATE_TIME.parseUnresolved(a, new ParsePosition(0));
tacc.get(ChronoField.SECOND_OF_MINUTE);
hasSecondPart = true;
} catch (UnsupportedTemporalTypeException ex) {
hasSecondPart = false;
}
System.out.println(hasSecondPart); // true for input b, false for input a
Side note:
An exception-free check if the string input has a second part or not would be possible with my library Time4J using this code:
boolean hasSecondPart =
Iso8601Format.EXTENDED_DATE_TIME.parseRaw(a).contains(PlainTime.SECOND_OF_MINUTE);

In ISO_DATE_TIME, seconds are optional (and set to zero if not present), that's why it parses both inputs. And LocalDateTime.toString() method will print the seconds only if it's not zero.
So, once you have the LocalDateTime objects created, you can't know if the original String had the seconds field.
To validate if the seconds field is present in the input String, you must create your own pattern and check if it throws exception when parsing:
// formatter with required seconds
DateTimeFormatter withSecs = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
LocalDateTime.parse(b, withSecs); // OK
LocalDateTime.parse(a, withSecs); // DateTimeParseException
If you want just to check if the field is present, but don't want to build a LocalDateTime object, you can also use parseUnresolved method, which doesn't throw exceptions:
ParsePosition position = new ParsePosition(0);
withSecs.parseUnresolved(a, position);
if(position.getErrorIndex() == -1) {
System.out.println("No error (it contains seconds)"); // b gets here
} else {
System.out.println("Error (it does not contain seconds)"); // a gets here
}

In Java 8 DateTime API
dates can be represented in the following way:
LocalDate as year-month-day
LocalDateTime as
year-month-day-hour-minute-second
ZonedDateTime as
year-month-day-hour-minute-second with time zone
As you can see, there is no way to differentiate between year-month-day-hour-minute-second and year-month-day-hour-minute. So, after the conversion from String to LocalDateTime is done - you can't differentiate it. The only way to do this is with String (either by length or regex), not with LocalDateTime object.

Related

Can't compare Strings

I am not able to compare the String returned from student.getUsername() to the hardcoded string(it is alway false even for correct values)
but when I use a normal string and not the one returned from student.getUsername() it is able to execute if block and return "login Success". I think the value returned from student.getUsername() is not comparable to String I even tried .toString() but no luck Please help.
#PostMapping()
public String setUser(#Valid #ModelAttribute("Student")Student student, Errors errors,
ModelMap model) {
String user = "das";
String pass = "12345";
if((student.getUsername()==user)&&(student.getPassword()==pass))return "loginSuccess";
else return "loginFailure"
You should use equals() method to compare the CONTENT of strings.
== operator in Java compares addresses of objects not theirs content :<

How do I avoid returning a null value while avoiding mutation?

I am trying to create a method that will take a list of items with set weights and choose 1 at random. My solution was to use a Hashmap that will use Integer as a weight to randomly select 1 of the Keys from the Hashmap. The keys of the HashMap can be a mix of Object types and I want to return 1 of the selected keys.
However, I would like to avoid returning a null value on top of avoiding mutation. Yes, I know this is Java, but there are more elegant ways to write Java and hoping to solve this problem as it stands.
public <T> T getRandomValue(HashMap<?, Integer> VALUES) {
final int SIZE = VALUES.values().stream().reduce(0, (a, b) -> a + b);
final int RAND_SELECTION = ThreadLocalRandom.current().nextInt(SIZE) + 1;
int currentWeightSum = 0;
for (Map.Entry<?, Integer> entry : VALUES.entrySet()) {
if (RAND_SELECTION > currentWeightSum && RAND_SELECTION <= (currentWeightSum + entry.getValue())) {
return (T) entry.getKey();
} else {
currentWeightSum += entry.getValue();
}
}
return null;
}
Since the code after the loop should never be reached under normal circumstances, you should indeed not write something like return null at this point, but rather throw an exception, so that irregular conditions can be spotted right at this point, instead of forcing the caller to eventually debug a NullPointerException, perhaps occurring at an entirely different place.
public static <T> T getRandomValue(Map<T, Integer> values) {
if(values.isEmpty())
throw new NoSuchElementException();
final int totalSize = values.values().stream().mapToInt(Integer::intValue).sum();
if(totalSize<=0)
throw new IllegalArgumentException("sum of weights is "+totalSize);
final int threshold = ThreadLocalRandom.current().nextInt(totalSize) + 1;
int currentWeightSum = 0;
for (Map.Entry<T, Integer> entry : values.entrySet()) {
currentWeightSum += entry.getValue();
if(threshold <= currentWeightSum) {
return entry.getKey();
}
}
// if we reach this point, the map's content must have been changed in-between
throw new ConcurrentModificationException();
}
Note that the code fixes some other issues of your code. You should not promise to return an arbitrary T without knowing the actual type of the map. If the map contains objects of different type as key, i.e. is a Map<Object,Integer>, the caller can’t expect to get anything more specific than Object. Besides that, you should not insist of the parameter to be a HashMap when any Map is sufficient. Further, I changed the variable names to adhere to Java’s naming convention and simplified the loop’s body.
If you want to support empty maps as legal input, changing the return type to Optional<T> would be the best solution, returning an empty optional for empty maps and an optional containing the value otherwise (this would disallow null keys). Still, the supposed-to-be-unreachable code point after the loop should be flagged with an exception.

TDD: What to test in code where is 800 and more possible outputs?

I have class that have properties IsMacro, Value, Visible, DataType and one method GetResolvedValue. I dont know what to test. I do some math and I figure out that there is over 800 possible outputs for that method.
enum DataTypeEnum:
Bool,
String,
DateTime,
Integer,
LongInteger,
Decimal,
...
class Macro
property bool IsMacro;
property string Value;
property bool Visible;
property DataTypeEnum DataType;
function GetResolvedValue(Resolver) {
string value = Value;
if (IsMacro && Visilbe) {
value = Resolver.resolve(value);
}
switch (DataType){
case String:
// returns value if is string e.g.: "text"
// othervise returns empty string
case Bool:
// returns value if is bool string e.g.: "true"
// othervise returns empty string
case DateTime:
// returns value if is DateTime string e.g.: "2/2/2010"
// othervise returns empty string
...
}
}
So it must always return string with value that is valid for associated datatype or empty string.
With this code there is a lot of combinations and I dont know how to test it. Shoud I test all posible solutions?
Listen to your tests!
Even now, before even being written, your tests tell you that this method massively violates the SRP and needs to be refactored.
You should probably extract a whole hierarchy of classes from this one method.

Accessing public static final field using JoSQL

I've been using JoSQL for quite a few months now and today I came across a problem I am not sure how to solve. I probably could solve it by binding variables/placeholders, but I'd like to include the fields in the query.
SELECT * FROM ...MyObject WHERE getType != com.mypackage.myclass.TYPE_A
This is the query that I have. TYPE_A is a public static final int attribute in "myclass" class. Accessing methods (such as getType) is easy, because getType is expected to be a method from MyObject - just that I do not write round brackets after it (this is how JoSQL works as far as I know).
Does anyone happen to have an idea how to access a public static final field?
JoSQL uses gentlyweb-utils; it seems to be some sort of Accessor/Getter/Setter framework. I'd love to access that attribute without having to bind variables, but I haven't been able to do so.
Thanks for your help in advance! I really appreciate it.
I think I have figured something out. First: it seems not possible to access the static variables for whatever reason. I've used the following approach to solve my issue:
create a method, which picks up a given JoSQL-statement
mark the constants, which you want to replace, by say "{?FULL_PACKAGE_AND$CONSTANT}"
use reflections to determine the column as well as the column (and value) from the field
iteratively replace the statement until no "{?"-values are available
Example:
JoSQL-statement looks like this:
(isWeapon = TRUE AND getItem.getType2 = {?com.l2jserver.gameserver.model.items.L2Item$TYPE2_WEAPON})
Method using the query-object:
final Query query = DataLayer.createJoSqlQuery(joSql);
Method (pre)processing the JoSQL-statement:
final Query query = new Query();
int variableColumn = 0;
while (joSql.indexOf("{?") > -1) {
variableColumn++;
final int startIndex = joSql.indexOf("{?");
final int endIndex = joSql.indexOf("}", startIndex);
final String value = joSql.substring(startIndex + 2, endIndex);
try {
final Object variableValue = Class.forName(value.split("\\$")[0]).getField(value.split("\\$")[1]).get(null);
query.setVariable(variableColumn, variableValue);
joSql = joSql.replace("{?" + value + "}", "?");
}
catch (...) {
e.printStackTrace();
}
}
query.parse(joSql);
return query;
The JoSQL-statement preprocessing method bascially iterates through a given JoSQL-statement and sees whether it contains the string "{?". If it does, it does some copy and paste (note the dollar-symbol right in front of the constant name).
Finally it creates the objects and sets them using something similar to prepared statements "setObject"-method. In the end it just replaces the values within the JoSQL-statement with question marks ("?") and sets a corresponding object in the newly created Query-object, which is later used to retrieve information.

KeyTyped key not showing key

I am trying to convert from processing to processingjs and have something I just can't understand.
In processing the following code returns whichever letter you type in, though in processingjs it just comes back with the keycode value but I need the letter not the code.
String name="";
void setup(){
size(200,200);
}
void draw(){
}
void keyPressed() {
if(key==ENTER) {
name="";
}
else {
name+=key;
println(name);
}
}
After hours of searching and the above answer I've found the answer here peepproject.com/forums/thread/266/view more eloquently than I. Basically the solution is to convert the int to a char() before constructing a String and putting it into an array.
Instead of name += key, try name += key.toString().
Processing's println automatically does type conversion for you, so the char value of PApplet.key gets printed as a letter. JavaScript string concatenation works differently; the integer value of PApplet.key will be appended to the string as an integer and will not automatically be converted to a string. You have to do it manually.
You need to use the char conversion function in Processing and Processing.js:
http://processingjs.org/reference/char_/
The reason why it's displaying as a number is this line:
char x = 97; //supposed to be an 'a'
Does a cast in Java (may require char x = (char)97).
However in processing.js it is executed as:
var x = 97;
Since javascript has dynamic typing. You therefore need to explicitly force type casts such as from int->char.

Resources