I need only to show suffix for day/days, how can I achieve that?
It doesn't work:
java.lang.IllegalStateException: No field to apply suffix to..
private PeriodFormatter getDayTextFormatter() {
return new PeriodFormatterBuilder()
.printZeroNever()
.appendSuffix("day", "days")
.toFormatter();
}
I don't think it's possible. According to JodaTime's javadoc, the appendSuffix method will throw an exception if there's no field to append the suffix:
Throws: IllegalStateException - if no field exists to append to
So I believe JodaTime can't help you this time. Although, you could do something like this:
private String suffix(Period p) {
int days = p.getDays();
if (days <= 0) {
return "";
}
return days == 1 ? "day" : "days";
}
With this code, the following:
System.out.println(suffix(Period.days(1)));
System.out.println(suffix(Period.days(2)));
System.out.println(suffix(new Period()));
produces the output:
day
days
// and a line with an empty string
Related
This question already has answers here:
SimpleDateFormat.parse() ignores the number of characters in pattern
(5 answers)
Closed 7 years ago.
I am working on a project where I need to validate multiple dates based on length and patterns. I am using simple date format and found many issues with that. My requirement is to strictly allow if date string matches "yyyy/MM/dd" and strictly 10 characters.
The below code is not giving expected results for various testing input strings.
public static boolean checkformat(String dateString){
boolean flag = false;
Date d1 = null;
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
format.setLenient(false);
try {
d1 = format.parse(dateString);
flag=true;
} catch (ParseException ex) {
ex.printStackTrace();
return false;
}
return flag;
}
the above code is returning "true" for various inputs like "99/03/1" (should be 0099/03/01) and 99/1/1( should be 0099/01/1). Since the input strings are not coming from a from so I cant perform validations before passing them to this method. Please suggest any implementation which should act very strict towards the dateformat("yyyy/MM/dd").
I suggest that you should try to validate date with regex before format it.
user below code for validate
public static boolean checkformat(String dateString){
boolean flag = false;
Date d1 = null;
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
format.setLenient(false);
try {
if (dateString.matches("([0-9]{4})/([0-9]{2})/([0-9]{2})")) { // use this regex
d1 = format.parse(dateString);
flag=true;
}
} catch (ParseException ex) {
ex.printStackTrace();
return false;
}
return flag;
}
Okay, first: You know what format you're expection. So why just parse it and catch an exception rather than checking preconditions ?
if(dateString.size() > 10) {
...
What you are actually doing is not checking your input format but rather parsing it - though the method is not expressing this contract -
so if your method is just for checking you could:
1. Use a regex
2. ... ?
I know that are quiet a lot of answers on the net which propose using SimpleDateFormat, but - to be frank -they are wrong.
If I am expecting a given format, e.g. as I know that conversions have been made on some user input, I can start parsing a string, and considering that something may have gone wrong, catch the exception. If I don't know which format is passed to me, I am at the validation layer and this layer should not try to perform a conversion but rather proof that the conversion would be valid.
You could try using the new java.time package from Java 8 and later. You could use it as so to replace the SimpleDateFormat:
public static boolean checkformat(String dateString){
boolean flag = false;
try {
TemporalAccessor ta = DateTimeFormatter.ofPattern("yyyyMMdd").parse(strDate);
flag=true;
} catch (DateTimeParseException ex) {
ex.printStackTrace();
return false;
}
return flag;
}
This would also limit the values from making no sense (e.g. month value being 18).
String[] removeSlashes=new String[3];
removeSlashes = enteredDate.split("/");
if(removeSlashes[0].length()!=4)
throw new IncorrectDateFormatException(); // user defined exception
if(removeSlashes[1].length()!=2)
throw new IncorrectDateFormatException();
if(removeSlashes[2].length()!=2)
throw new IncorrectDateFormatException();
//Then use SimpleDateFormat to verify
I needed to set all zeros in Timestamp instance.
Here is the code I tried
import java.sql.Timestamp;
public class UI
{
public static void main(String args[])
{
Timestamp timestamp = Timestamp.valueOf("0000-00-00 00:00:00.0");
System.out.println(timestamp);
}
}
It is showing output
0002-11-30 00:00:00.0
How to set the value of Timestamp so that output will show
0000-00-00 00:00:00.0
It is not possible to instantiate a Timestamp to 0000-00-00 00:00:00.
valueOf calls a constructor, which in the source code has the following javadocs (taken from offical javadocs API):
Constructs a Timestamp object initialized with the given values.
Deprecated: instead use the constructor Timestamp(long millis)
Parameters:
year the year minus 1900
month 0 to 11
date 1 to 31
hour 0 to 23
minute 0 to 59
second 0 to 59
nano 0 to 999,999,999
The date parameter must be of value between 1-31.
'0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
Try this
public class Test {
public static void main(String[] args) {
try {
String[] s = {"0001-01-01 00:00:00.0", "0000-00-00 00:00:00"};
for (String value : s) {
Timestamp t = Timestamp.valueOf(value);
System.out.println(t.toString() + ", " + t.getTime());
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
There is no 0th month which has a 0th day (and no 0th year depending on your calendar). If you want to change how the timestamp prints you can do this
Timestamp ts = new Timestamp(Long.MIN_VALUE) {
public String toString() {
return "0000-00-00 00:00:00.0";
}
};
This will print the way you expect.
A quick check on the java.sql.Timestamp Documentation reveals that the Class - Timestamp only supports the following parameter values:
year - the year minus 1900
month - 0 to 11
date - 1 to 31
hour - 0 to 23
minute - 0 to 59
second - 0 to 59
nano - 0 to 999,999,999
So, the answer to your question is that, you cannot set the value to:
0000-00-00 00:00:00.0
However, you can set the hour, minute, second and nanosecond value to 00:00:00.0.
Were you able to execute your code successfully?
Executing your code resulted in:
Exception in thread "main" java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
at java.sql.Timestamp.valueOf(Unknown Source)
It is actually possible to do this via reflection. Internally the timestamp object has another date object which is not accessible outside.
public static void convertTimestampToZero(final Timestamp t) {
// normalize the timestamp to generate internal date object
t.toString();
// reset the nano seconds
resetInternalDateField(t, "fastTime");
resetInternalDateField(t, "nanos");
// get the internal date object
Field cdateField = getDeclaredFieldInHierarchy(t.getClass(), "cdate");
Object cdate = getIgnoreAccess(t, cdateField);
// convert fields to zero
resetInternalDateField(cdate, "year");
resetInternalDateField(cdate, "month");
resetInternalDateField(cdate, "dayOfMonth");
resetInternalDateField(cdate, "dayOfWeek");
resetInternalDateField(cdate, "hours");
resetInternalDateField(cdate, "minutes");
resetInternalDateField(cdate, "seconds");
resetInternalDateField(cdate, "millis");
resetInternalDateField(cdate, "fraction");
}
private static void resetInternalDateField(final Object o, final String fieldName) {
Field field = getDeclaredFieldInHierarchy(o.getClass(), fieldName);
setIgnoreAccess(o, field, 0);
}
public static Field getDeclaredFieldInHierarchy(final Class<?> cls, final String fieldName) {
if (null == cls) {
return null;
}
List<Field> fields = getDeclaredFieldsInHierarchy(cls);
for (Field field : fields) {
if (field.getName().equals(fieldName)) {
return field;
}
}
return null;
}
Just implement the getIgnoreAccess/setIgnoreAccess methods which just get/set the value of a field via reflection ignoring the access modifiers.
And here's a test:
#Test
void shouldGenerateAZeroTimestamp() {
Timestamp t = new Timestamp(4324629);
convertTimestampToZero(t);
assertThat(t.toString(), equalTo("0000-00-00 00:00:00.0"));
}
I have an ArrayList including several number of time-stamps and the aim is finding the difference of the first and the last elements of the ArrayList.
String a = ArrayList.get(0);
String b = ArrayList.get(ArrayList.size()-1);
long diff = b.getTime() - a.getTime();
I also converted the types to int but still it gives me an error The method getTime is undefined for the type String.
Additional info :
I have a class A which includes
String timeStamp = new SimpleDateFormat("ss S").format(new Date());
and there is a class B which has a method private void dialogDuration(String timeStamp)
and dialogueDuration method includes:
String a = timeSt.get(0); // timeSt is an ArrayList which includes all the timeStamps
String b = timeSt.get(timeSt.size()-1); // This method aims finding the difference of the first and the last elements(timestamps) of the ArrayList (in seconds)
long i = Long.parseLong(a);
long j = Long.parseLong(b);
long diff = j.getTime()- i.getTime();
System.out.println("a: " +i);
System.out.println("b: " +j);
And one condition is that the statement(String timeStamp = new SimpleDateFormat("ss S").format(new Date());) wont be changed in class A. And an object of class B is created in class A so that it invokes the dialogueDuration(timeStamp) method and passes the values of time-stamps to class B.
My problem is this subtraction does not work, it gives an error cannot invoke getTime() method on the primitive type long. It gives the same kind of error also for int and String types?
Thanks a lot in advance!
Maybe like this:
SimpleDateFormat dateFormat = new SimpleDateFormat("ss S");
Date firstParsedDate = dateFormat.parse(a);
Date secondParsedDate = dateFormat.parse(b);
long diff = secondParsedDate.getTime() - firstParsedDate.getTime();
Assuming you have Timestamp objects or Date Objects in your ArrayList you could do:
Timestamp a = timeSt.get(0);
Timestamp b = timeSt.get(timeSt.size()-1);
long diff = b.getTime() - a.getTime();
You can calculate the difference with the both following methods(also you can modify the mentioned methods to return difference as 'millisecond', 'day', 'month', etc by adding additional if statement or using switch case):
private Long calculateDifference(String date1, String date2, String value) {
Timestamp date_1 = stringToTimestamp(date1);
Timestamp date_2 = stringToTimestamp(date2);
long milliseconds = date_1.getTime() - date_2.getTime();
if (value.equals("second"))
return milliseconds / 1000;
if (value.equals("minute"))
return milliseconds / 1000 / 60;
if (value.equals("hours"))
return milliseconds / 1000 / 3600;
else
return new Long(999999999);
}
private Timestamp stringToTimestamp(String date) {
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date parsedDate = dateFormat.parse(date);
return new Timestamp(parsedDate.getTime());
} catch (Exception e) {
return null;
}
}
For example:
calculateDifference("2021-10-20 10:00:01", "2021-10-20 10:15:01", "minute");
will return '-15'
or
calculateDifference("2021-10-20 12:00:01", "2021-10-20 10:15:01", "minute");
will return '105'
You should make your ArrayList x to an ArrayList<TimeStamp> x. Subsequently, your method get(int) will return an object of type TimeStamp (instead of a type String). On a TimeStamp you are allowed to invoke getTime().
By the way, do you really need java.sql.TimeStamp? Maybe a simple Date or Calendar is easier and more appropriate.
I want to convert a string into a date, this is simple. But what I'd like to do it without knowing the date format.
Here is a situation: say I have 100 dates and all are in the same format but I'd like to write a Java program to find out this format for me. The result of this program should give me a list of all the possible formats.
For example:
06-06-2006
06-06-2009
...
06-13-2001 <- 99th record
the result of this will give me date format can be mm-dd-yyyy
If the 99th record also was 06-06-2006 the result should be mm-dd-yyyy and dd-mm-yyyy.
Can someone please help me with an example?
Seems sensible to create a set of formats you know about (DATE_FORMATS) and then test each line to see which formats understand every line. You should end up with a set of possibilities.
public class DateFormatDetector {
private static final Set<String> DATE_FORMATS = new HashSet<String>();
static {
DATE_FORMATS.add("yyyy-MM-dd");
DATE_FORMATS.add("dd-MM-yyyy");
DATE_FORMATS.add("MM-dd-yyyy");
}
public static Set<String> getPossibleDateFormats(List<String> dates) {
Set<SimpleDateFormat> candidates = new HashSet<SimpleDateFormat>();
for (String df : DATE_FORMATS) {
SimpleDateFormat candidate = new SimpleDateFormat(df);
candidate.setLenient(false);
candidates.add(candidate);
}
for (String date : dates) {
Iterator<SimpleDateFormat> it = candidates.iterator();
while (it.hasNext()) {
SimpleDateFormat candidate = it.next();
try {
// try to parse the string as a date
candidate.parse(date);
}
catch (ParseException e) {
// failed to parse, so this format is not suitable
it.remove();
}
}
}
Set<String> results = new HashSet<String>();
for (SimpleDateFormat candidate : candidates)
results.add(candidate.toPattern());
return results;
}
}
Try to use SimpleDateFormat prepare all possible formats and calculate parsed result.
The solution could be functional Java as described for example in the stack overflow
I have a window that contains a HH:mm time TextField in it, in 24 hours format
I need to validate if the user entered any non valid hour, like 28:00, 99:00, 24:01.
What's the best and simpler way to do that ?
some code below of what is currently doing that job wrong and giving errors in date parsed.
Today I get an random hour and an user hit 99:99 in that text field.
This code is not mine, but I gotta fix it.
I am stuck with it, tried to validate as a String is useless, and I cannot find a nice way to make it a Date without having to put year, month, etc... too.
Please forget about the return -1 instead of throwing an exception this is old code and this cannot be changed.
to help understand :
Statics.hF2 = SimpleDateFormat (HH:mm)
this.cmpHora.getText() = Is the field with the value
Statics.df_ddmmyy = Another date format
Statics.m2ms = converts minutes to milliseconds
//CODE
public long getDataEmLong ()
{
try
{
Calendar hour= Calendar.getInstance();
new GregorianCalendar().
hour.setTime( Statics.hF2.parse( this.cmpHora.getText() ) );
return Statics.df_ddmmyy.parse( this.cmpData.getText() ).getTime() + Statics.m2ms( hour.get( Calendar.HOUR_OF_DAY ) * 60 ) + Statics.m2ms( hour.get( Calendar.MINUTE ) );
} catch ( Exception e )
{
e.printStackTrace();
return -1;
}
}
Cheers !
Regular expressions to the rescue:
public boolean validTime24(String time) {
return time.matches("^([01]\d|2[0-3]):[0-5]\d$")
}
This will validate the format of the string. Then you can parse out the time from there.
Insert this in your class, and perform the validateTime method from inside your junk code.
public boolean validateTime(String timeString) {
if (timeString.length() != 5) return false;
if (!timeString.substring(2, 3).equals(":")) return false;
int hour = validateNumber(timeString.substring(0, 2));
int minute = validateNumber(timeString.substring(3));
if (hour < 0 || hour >= 24) return false;
if (minute < 0 || minute >= 60) return false;
return true;
}
public int validateNumber(String numberString) {
try {
int number = Integer.valueOf(numberString);
return number;
} catch (NumberFormatException e) {
return -1;
}
}
You can use JFormattedTextField with proper Date or Time Format set. The field will return you proper values.
Since Java 8 you can use DateTimeFormatter:
public boolean validate(String time) {
try {
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
timeFormatter.parse(time);
return true;
} catch (DateTimeParseException e) {
return false;
}
}