Date-format Behaving Peculiarly - java

we have a legacy system where they would be generating the current date and then sets that as a header to an excel.
Below java code in the simplified piece of my logic
Sometimes for this program I get the header output in a peculiar form
As example scenario is my code is supposed to produce an header of 14 characters like 20170529121599 but sometimes it is producing a header of 15 characters like 201705291215992
Expected : 20170529121599
Output : 201705291215992
Why am I getting that extra character in some rare cases ?
This happens very rarely only and when this happens this extra character is causing the downstream system to fail.
Fix : We can fix this by timing the extra charters but I really want to know the reason behind this so that it would help to fix similar issues.
Can someone help me with this ?
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class TestDateGeneration {
public static void main(String args[]) {
DateFormatSymbols symbols;
SimpleDateFormat formatter;
symbols = new DateFormatSymbols(new Locale("en", "US"));
formatter = new SimpleDateFormat("E", symbols);
java.util.Date todayDate = new java.util.Date();
String header = "";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String formatedDate = dateFormat.format(todayDate);
header = formatedDate+"\t";
System.out.println("output header " +header);
}
}

Besides being incredibly difficult to read, your code doesn't produce your output (hint: include "formatedDate" in your println() call). An actual failing test would probably result in a better answer.
So if I were to guess at why it's not doing what you want, I would guess that your format is actually "yyyyMMddHHmmSS". The capital S means milliseconds (which is consistent with what your reported output shows). Note that "99" is invalid for seconds in the minute, but "990" and "992" are both valid milliseconds.

Related

Why does the NumberFormat returns blank fields?

So a few days ago I encountered a weird problem however, I didn't change any that kind of code. The problem is the format I'm getting from my method which I used for years. All commas are now spaces (blank fields) and I have no idea what is causing this.
public static String toFancyCost(int num) {
return NumberFormat.getInstance().format((Integer) num);
}
Before even this happened the String I received was looking like for example 2,181,273 and not like 2 181 273.
You must have changed your system locale by accident. The implementation of NumberFormat.getInstance() (on 1.8.0_131):
public final static NumberFormat getInstance() {
return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
}
It uses formatting specified by the default locale. and the java docs on Locale.getDefault say:
The Java Virtual Machine sets the default locale during startup based
on the host environment. It is used by many locale-sensitive methods
if no locale is explicitly specified. It can be changed using the
setDefault method.
If you were to use NumberFormat.getInstance(Locale) you can specify which locale the NumberFormat should use.
Your systems default local is using a space as thousands separator, number format retured by getInstance() uses settings from system's default local.
As commented above, somehow the system default may have been modified. Let's stick the code to set the locale when formatting by using below to avoid any issues.
int number = 345678987;
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US);// Locale.US or any other locale you required
String numberAsString = numberFormat.format(number);
System.out.println(numberAsString);
response:
345,678,987
when I use the below for example with Locale.CANADA_FRENCH
int number = 345678987;
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
String numberAsString = numberFormat.format(number);
System.out.println(numberAsString);
response:
345 678 987
So in your case also locale may have been causing issues, so please explictly set locale.

Java Date Format parse function failing when submitting a form to a controller in Internet Explorer

I am running into an issue with Date parsing in IE 11. It seems to be occurring in Edge as well. Please have a look at the following Java code. This below code is part of a controller method that a form is submitted to.
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
stream.setAutoExpireDate(dateFormat.parse(request.getParameter("autoExpireDate")));
The output of request.getParameter("autoExpireDate") is "05/30/2018".
When parse is called on that specific date format, passing that string, it hits the following DateFormat.java function:
public Date parse(String source) throws ParseException
{
ParsePosition pos = new ParsePosition(0);
Date result = parse(source, pos);
if (pos.index == 0)
throw new ParseException("Unparseable date: \"" + source + "\"" ,
pos.errorIndex);
return result;
}
For some reason, and only in IE/Edge, I keep getting the following error:
Unparseable date: "‎05‎/‎30‎/‎2018"
I am very confused as to why this is an "unparseable" date. The same date string seems to work fine with Chrome and Firefox when I submit the form through the application.
Obviously, pos.index == 0 in the parse function is equaling 0 when the value is passed, but for what reason? Why would IE/Edge be behaving in such a manner?
I apologize if anything is unclear. Feel free to ask any questions and I will further clarify. Any help is greatly appreciated.
Best Regards,
MotoDave452
UPDATE: While request.getParameter("autoExpireDate") is a string that equals "‎05‎/‎30‎/‎2018", check out the differences in the actual value when using IE compared to Chrome.
IE:
Chrome:
It appears IE is adding non-printable characters to your date. Try the following:
dateStr = source.replaceAll("\\p{C}", "");
There is a problem in IE 11 Date Parser, doesn't like unicode characters, it mean, you have to replace them, with something like this
Date dateStr = new Date().toLocaleString().replace(/[^A-Za-z 0-9 \.,\?""!##\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g, '');
Date date = new Date(dateStr);
to avoid the non-asci characters

Using DateFormat.getDateTimeInstance().format(date);

When running some tests I came across the following issue. When using:
private String printStandardDate(Date date) {
return DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT).format(date);
}
I found this produced different formats of Date depending on the location the tests where run from. So locally in windows / eclipse I got a result: 04/02/12 18:18 but on the Linux box in America I get 2/4/12 6:18 PM
This causes my Tests/Build to fail:
expected:<[04/02/12 18:18]> but was:<[2/4/12 6:18 PM]>
Could anyone explain this behavior?
That's not strange, that's exactly how it's supposed to work.
The API documentation of DateFormat.getDateTimeInstance says:
Gets the date/time formatter with the given date and time formatting styles for the default locale.
The default locale is different on your Windows system than on the Linux box in America.
If you want exact control over the date and time format, use SimpleDateFormat and specify the format yourself. For example:
private String printStandardDate(Date date) {
return new SimpleDateFormat("dd/MM/yy HH:mm").format(date);
}
Even better would be to re-use the SimpleDateFormat object, but beware that it is not thread-safe (if the method might be called from multiple threads at the same time, things will get messed up if those threads use the same SimpleDateFormat object).
private static final DateFormat DATE_FORMAT =
new SimpleDateFormat("dd/MM/yy HH:mm");
private String printStandardDate(Date date) {
return DATE_FORMAT.format(date);
}
The format is based on the default locale in your code. If you want to ensure results you must make sure to use a specific locale. The getDateTimeInstance method is overloaded to offer an alternative method that receives the locale that you want to use as parameter.
public static final DateFormat getDateTimeInstance(int dateStyle,
int timeStyle,
Locale aLocale)
If you use the same locale in both testing environments, the result should be the same.

Custom date format in android for given locale

I'm trying to format a date for a given locale new Locale("mk", "MK"). The locale is valid, it returns the country name and language properly. I want to use custom string, in my case "E, kk:mm" or "EEEE, kk:mm". I want the output to be "сабота, 12:00", but what I get is "7, 12:00".
This is how I use it and I tried many ways, but they all seem to behave the same.
SimpleDateFormat sdf = new SimpleDateFormat("EEEE, kk:mm", new Locale("mk", "MK));
sdf.format(new Date());
// output: 7, 12:30
Another method I tried
Calendar calendar = Calendar.getInstance(new Locale("mk", "MK"));
calendar.setTimeInMillis(new Date().getTime());
DateFormat.format("EEEE, kk:mm", calendar);
// output: Saturday, 12:30
I also tried using java.text.DateFormat instead android class, but no change.
The phone locale is set to English, but this is localized app, I want to show dates in a fixed locale format.
I've looked into many SO question regarding this issue and I wasn't able to find answer. I'm not interested in predefined formats, I want to use my own format and I want the date/month names to be formatted for the input locale.
I think the problem is that Macedonia is not a supported locale on the Android JVM. If you run your code as plain Java console app, it's fine. The method Locale.getAvailableLocales() returns 152 members in plain Java, only 88 in an Android emulator. If you have the code snippet:
Locale[] locales = Locale.getAvailableLocales();
String cCode;
for (Locale loc :locales){
cCode = loc.getCountry();
if (cCode.equalsIgnoreCase("MK"))
Toast.makeText(this, cCode, Toast.LENGTH_SHORT).show();
// Or System.out.println() in a Java app
}
Then the toast doesn't show for "MK" although it will println in the Java app
From documentation of SimpleDateFormat:
**Text**: For formatting, if the number of pattern letters is 4 or more,
the full form is used; otherwise a short or abbreviated form is used if
available. For parsing, both forms are accepted, independent of the
number of pattern letters.
So this should fix it:
SimpleDateFormat sdf = new SimpleDateFormat("EEEE, kk:mm", new Locale("mk", "MK"));
NickT was faster :-), so just adding to his answer: if you want to see your locales supported on Android, run:
for (Locale l:Locale.getAvailableLocales()) {
Log.d(l.getDisplayCountry(),l.toString());
}
and you will see that Macedonia is not on the list.

DecimalFormat depending on system settings?

I'm having the strangest thing with a DecimalFormat.
I'm using it in an webapplication.
I setup some test and it keeps on failing with me locally.
A friend of me ran it and he was able to successfully ran the JUnit tests.
The strange part is that on our server the application runs it perfectly without any problems either.
Could it be that Java depends on the system settings like valuta and number settings?
Or could there be another reason?
This is how my piece of code looks like:
public String generateFormatPrice(double price) throws Exception {
DecimalFormat format1 = new DecimalFormat("#,##0.00");
String tmp = format1.format(price).replace(".", "&");
String[] tmps = tmp.split("&");
return tmps[0].replace(',', '.') + "," + tmps[1];
}
Thanks a lot in advance!
This code is indeed locale-specific. If your code depends on being in a locale such as the USA where "." is the decimal separator and "," is the thousands separator, and then you run this code on a server set to, for example, the German locale, it will fail.
Consider using this constructor, which allows you to explicitly specify which symbols you are using.
EDIT: as far as I can tell you are trying to format numbers using "." as the thousands separator and "," as the decimal separator. In other words, the format used in France and Germany. Here's one approach that will achieve this:
public static String generateFormatPrice(double price) {
final NumberFormat format = NumberFormat.getNumberInstance(Locale.GERMANY);
format.setMinimumFractionDigits(2);
format.setMaximumFractionDigits(2);
return format.format(price);
}
Also, you shouldn't be using a double to hold a monetary value - you are going to encounter some nasty bugs if you do that.

Categories

Resources