Android SimpleDateFormat for a two digit month - android

I have a database in my Android app that has dates formatted like this: 201274 for July 4, 2012 and 20121016 for October 16, 2012. I display the date of the DB row using SimpleDateFormat so that for today, it grabs the date 20121016 and displays 2012-10-16. The code is like so:
private void convertDBdate() {
convertDateTextView.setText(gotDt);
String dateStr = convertDateTextView.getText().toString();
SimpleDateFormat inputFormatter = new SimpleDateFormat("yyyyMd");
SimpleDateFormat outputFormatter = new SimpleDateFormat("yyyy-MM-dd");
try {
DBdate = inputFormatter.parse(dateStr);
dashDateStr = outputFormatter.format(DBdate);
convertFinalDateTV.setText(dashDateStr);
} catch (ParseException e ) {
e.printStackTrace();
}
With this code, 201274 displays fine as 2012-07-04, but two digit months display incorrectly, 20121016 shows as 2012-01-16 (January 16). The problem is in the MM and dd. I've tried yyyy-M-dd as the output date format, but that shows 2012-1-16 (again, January 16).
Do I have to somehow isolate the M value and do that month + 1 thing? If so how would that be written, and where would it go?
I don't want to have to re-write the dates in the database to 20120704 for July 4, 2012, I'd like to be able to fix it in code.

Your problem isn't that the input formatter should always be yyyyMMdd but that sometimes it should be yyyyMMdd
in the case of 201274 then an input format of MM won't apply but in the case of 20121016 then it will.
You'll need to add some logic parsing the length of the input and choosing the appropriate formatter.
Before I could suggest some logic I'd need to ask two questions
How do you represent 2012-10-01 in the database? I guess that it's 2012101 in which case...
How do you distinguish between 2012111 and 2012111? i.e. 2012-11-01 and 2012-01-11

maybe to late for this project but for future projects I would always recommend to use
Date.getTime()
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Date.html#getTime()
for storing even dates as it will take less space in the database, will make sorting faster and you just avoid problems you have right now.

Related

Different Date Formats

I got a Problem when converting a Date in my Android App.
My Problem is that I got two different Formats of the Date.
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
DateFormat formatter_date = new SimpleDateFormat("dd.MMM.yyyy");
Date myDate = null;
try {
myDate = dateFormat.parse("28.10.2015");
} catch (ParseException e) {
e.printStackTrace();
}
formatter_date.format(myDate,"dd.MM.yyyy"))
txtDate.setText(formatter_date.format(myDate,"dd.MM.yyyy")));
I want to have the date formatted as 28.Oct.2015 on a device set to English language, as 28.Okt.2015 in German, etc. So always one dot before and after the month abbreviation. When language is set to English it returns 28.Oct.2015 as it should, however, when Language is set to German it returns 28.Okt..2015 with two dots between Okt and 2015.
Is there any solution to handling this?
I should like to challenge what you are asking for. Of course you can have it, as your own answer already shows. But do you want it?
Use the built-in localized formats
Java has localized formats for all available locales (I think it’s all, in any case it’s many). I suggest you use these rather than your own idea of what a localized date should look like. While 28.Okt.2015 is probably commonplace in Austria and other German-speaking places, English-speaking people are not used to the dots in your format, and I would suspect that some people in the world will find it more or less strange.
I suggested in a comment that you add ThreeTenABP to your Android project in order to use java.time, the modern Java date and time API. It is so much nicer to work with. Now I am taking my own medicine:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
LocalDate myDate = LocalDate.of(2015, Month.OCTOBER, 28);
System.out.println(myDate.format(dateFormatter));
Output in different locales include:
German: 28.10.2015
UK English: 28 Oct 2015
French: 28 oct. 2015
It’s not what you asked for. And you may meet objections, but that will happen no matter which format you choose because many people have their own ideas about the proper formatting for their locale. It’s pretty standardized, though, so consider it.
Edit: where did the LocalDate come from?
I understood that you were converting from a string like "28.10.2015". Converting this to a LocalDate is straightforward when you know how:
DateTimeFormatter numericDateFormatter = DateTimeFormatter.ofPattern("dd.MM.uuuu");
LocalDate myDate = LocalDate.parse("28.10.2015", numericDateFormatter);
Only if you got a java.util.Date from a legacy API that you cannot change or do not want to change just now, first thing convert it to the modern Instant type and do further conversions from there:
LocalDate myDate = oldfashionedJavaUtilDate.toInstant()
.atZone(ZoneId.of("Europe/Vienna"))
.toLocalDate();
Since this is a time zone sensitive operation, I recommend you specify an explicit time zone. You may use the JVM’s time zone setting by specifying ZoneId.systemDefault(), but be aware that this is fragile: the JVM setting may be changed under your feet by other parts of your program or other programs running in the same JVM.
What you asked for
The java.time edition of what you asked for is pretty similar to the code in your own answer:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd");
DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("MMMM");
DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern("uuuu");
LocalDate myDate = LocalDate.of(2015, Month.OCTOBER, 28);
String dayOfMonth = myDate.format(dateFormatter);
String monthName = myDate.format(monthFormatter);
if (monthName.length() > 3) {
monthName = monthName.substring(0, 3);
}
String year = myDate.format(yearFormatter);
String formattedDate = dayOfMonth + '.' + monthName + '.' + year;
System.out.println(formattedDate);
Output in the same locales as above:
German: 28.Okt.2015
UK English: 28.Oct.2015
French: 28.oct.2015
There is a much shorter way to obtain the same, though:
String formattedDate = String.format("%1$td.%2$.3s.%1$tY",
myDate,
myDate.getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault()));
It’s harder to read. It took me a number of attempts to get the format string %1$td.%2$.3s.%1$tY exactly right. And it will surprise those maintaining your code if they are used to DateTimeFormatter for formatting dates (and times). So I don’t really recommend it, but the choice is yours.
With another date I got the following output in French locale:
08.jui.2018
No French-speaking person, nor anyone else for that matter, will know whether this date was in June (juin) or July (juillet). In 57 of the available locales in my JVM, all 12 months of the year begin with the same three letters. Such locales include Tibetan, Swahili, Somali, Cornish, Scottish Gaelic and Vietnamese. In these languages nobody will be able to tell any months apart. Please think twice.
Links
Oracle tutorial: Date Time, explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
SimpleDateFormat dateFormat = new SimpleDateFormat(String pattern, Locale locale);
has another constructor with Locale change Locale.ENGLISH for date to be set in English. You can check other Locale options. I generally use Locale.getDefault() to display date in user's prefered language.
Thanks for help but this solution works best for me
DateFormat formatter_month = new SimpleDateFormat("MMMM"); //Get Whole Name of Month
DateFormat formatter_day = new SimpleDateFormat("dd."); //Get Day + Dot(2 digits)
DateFormat formatter_year = new SimpleDateFormat(".yyyy"); //Get Dot + Year(4 digits)
String str_date = formatter_day.format(date)+ //Day
formatter_month.format(date).substring(0,3)+ //Month
formatter_year.format(date); //Year

Issue with formatting time zone for Joda DateTime from ISO String

So time formatting and adjusting has always been my biggest nemesis in programing and I'm having some issues in Android/Java that I can't figure out. I get a timestamp from a server that is formatted in UTC (here's an example 2016-06-17T18:30:00-07:00. Now this time needs to get formatted to the users local time (so for a user in PST it should show as 11:30AM) but so far whatever I try I either get 1AM or 6:30PM (so I know I'm doing something wrong I just don't know what). Here's what I've been trying to do
public static DateTime convertISOStringToDate(String inputString) {
//setup the ISO Date Formatter with GMT/UTC format
DateTimeFormatter formatter = ISODateTimeFormat.dateTimeParser()
.withLocale(Locale.US)
.withZone(DateTimeZone.forOffsetHours(0));
DateTime dateTime = formatter.parseDateTime(inputString);
//now convert the datetime object to a local date time object
DateTimeFormatter localFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withZone(DateTimeZone.getDefault());
String localString = localFormatter.print(dateTime);
DateTime localDateTime = localFormatter.parseDateTime(localString);
return localDateTime;
So at this point I'm getting 1:30AM, so I know I'm messing it up somewhere in the conversion process but I can't figure it out. I've been trying to google around but so far haven't found much that use the ISODateTimeFormat parser so they don't work either when I try them.
You seem to have a basic mis-understanding of how dates are represented.
A date (in almost every known programming language / library) is represented internally as an offset from a specific 'origin time', known as the 'Epoch'.
In java.util.Date as well as joda dates, the internal representation is the number of milliseconds since midnight, Jan 1, 1980, UTC.
As such, a date does not have a timezone. You only introduce a timezone when you format a date (turn it into a String representation of the date).
You have made the common mistake of parsing a String into a date object, serializing (printing) it back out with a different timezone than the the original string indicated, and then parsing back into a date again, expecting something to have changed. If you do that correctly, you will get back exactly the same date that you started with.
In your case, the "localString" that you get shows the correct time in the local timezone. I'm in EDT, which is UTC-4:00, and I correctly get 2016-06-17 21:30:00 as the result.
As I said, parsing that back into a DateTime, and then looking at it is useless, because:
You'll get the same DateTime back that you started with
Your IDE (or whatever you're using to inspect the DateTime) probably isn't showing what you expect.
You should re-evaluate what you're doing here, and whether you really need to "convert" the DateTime, or to just parse it, and really understand how date formatting works with respect to timezones.

Joda library does not work properly

I'm using Joda library in my android application to calculate the duration between two given dates. Using this application to calculate a person's age.
The following code gives this output : 23 years 11 months and 6 days
DateTime from_readable_dateTime = new DateTime(from_date_dt);
DateTime to_readable_dateTime = new DateTime(to_date_dt);
Period period = new Period(from_readable_dateTime, to_readable_dateTime);
from_date_dt in this case is 1990/01/06 and to_date_dt is 2014/09/15. (date format is yyyy/mm/dd). As I mentioned earlier the output of this piece of code with the given inputs must be 24 years, 7 months and 20 days while I get 23 years 11 months and 6 days. What's the problem? Am I doing something wrong or Joda is faulty?
UPDATE-1
I get 3 numbers as year, month and day from 3 number pickers I make a single string as date(start date variable is named from_date_string and end date is named to_date_string), I convert these two strings to date variables (from_date_dt and to_date_dt):
from_date_dt = null;
to_date_dt = null;
diff_dt = null;
dateFormat = new SimpleDateFormat("yyyy/mm/dd");
try {
from_date_dt = dateFormat.parse(from_date_string);
to_date_dt = dateFormat.parse(to_date_string);
} catch (ParseException e) {
e.printStackTrace();
}
BTW, I'm working with Persian calendar. Since I can't use the default date picker, I'm using number pickers as date pickers.
The standard period type which you implicitly use contains weeks. The class Period has another constructor with 3 arguments where you can specify PeriodType.yearMonthDay() as third argument.
LocalDate d1 = new LocalDate(1990, 1, 6);
LocalDate d2 = new LocalDate(2014, 9, 15);
Period p = new Period(d1, d2, PeriodType.yearMonthDay());
System.out.println(p); // output: P24Y8M9D
To explain the result in fine-granular steps:
[1990-01-06] + 24 years = [2014-01-06]
[2014-01-06] + 8 months = [2014-09-06]
[2014-09-06] + 9 days = [2014-09-15]
Another thing to consider, don't use DateTime if your input is just a plain date format. Do you really want to take into account timezone effects? And why do you use SimpleDateFormat although JodaTime has its own formatters?
UPDATE after updated question of OP:
Now the question has become a lot clearer.
First to note generally, if you use number pickers then your original input for year, month and day-of-month are just integers. In that case I would normally not use a formatter at all, but just pass the numbers to the constructor of LocalDate. This constructor will also verify the input automatically. The complex conversion you try is very error-prone (number to string, then string concatenation to a date string, then parsing it with your default timezone and then passing java.util.Date to DateTime-ctor). It can be completely avoided.
Second to note and most important: You write that you use a persian calendar. Then the reason why you cannot use the default date picker is simply that this default date picker does not support the calendrical rules of persian calendar. Is my speculation right? And here the very bad news for you: Jodas classes do NOT support the persian calendar, too, especially LocalDate or DateTime are only designed for the ISO-8601-standard which is based on the modern proleptic gregorian calendar. Month lengths for example are different in gregorian calendar and in persian calendar, hence a completely different calendar arithmetic is required which is not supported by Joda-Time.
So your strange period results are probably explainable by the fact that you tried to let the user define persian year, month and day. And then you try to parse this input leniently (otherwise Joda-Time would immediately complain about odd day-values for example). But the last step - period calculation - must fail because it is based on ISO-8601 in Joda-Time and not persian calendar rules.
Am I right? Or have I misinterpreted your updated question?
A work-around is difficult. If you really want to have period calculation for a persian calendar then you have to build it from the scratch. As far as I know there is actually no library which supports this feature. A guideline for writing a persian solution can be the algorithm discussed in this SO-post however.
UPDATE indicating a solution:
Meanwhile I have implemented the Persian calendar in Time4A, see also this SO-post. So if you are able to use Time4A and combine the PersianCalendar with the algorithm for a multi-unit-period mentioned above then this will solve your problem. Time4A-v3.15-2016a explicitly supports special Persian calendar units which use different rules than gregorian calendar units.

SQLite Datetime Conversion?

I m developing android application. I need to convert datetime into date. I want to convert '25-07-2013 11:44AM' (datetime) into '25-07-2013' (date).
I am trying this function to convert SELECT date('25-07-2013 11:44AM'), but it was not working.Please suggest some solution for this problem.
According to this page, it does not seem that am/pm times are supported in date SQLite function (this should be noted as h or K according to the date format specification of Java at least; also it is explicitly mentioned %H hour: 00-24). Maybe experiment if using 24 hour clock will not trigger the issue.
I am not sure if you are search for Java code or SQL code , but if it is Java code then solution could be this :
String date = "25-07-2014 11:44AM";
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
String newDate = dateFormat.format(dateFormat.parse(date));
System.out.println(newDate);
If in case your are looking for SQL code let me know I will share that as well.

How to get user-selected date format in Android?

I have been working on problem of date format selected by users in the Android Phone.
I have gone through almost many question and answers on the stackoverlow and havent got the perfect answer.
For example:-
I have selected dateformat in phone is "Sat, 31 Dec 2011"
But when I used as based question answered on stackoverflow:-
DateFormat df = android.text.format.DateFormat.getDateFormat(context.getApplicationContext());
tv.setText(df.format(date));
Above code returns me 06/08/2011 (mm/dd/yyyy) format.
But see the date format i selected on phone. How can i get the exact format?
In an application I'm currently developing I use the following, which I believe will do what you require
final String format = Settings.System.getString(getContentResolver(), Settings.System.DATE_FORMAT);
if (TextUtils.isEmpty(format)) {
dateFormat = android.text.format.DateFormat.getMediumDateFormat(getApplicationContext());
} else {
dateFormat = new SimpleDateFormat(format);
}
The DateFormat.getDateFormat works as expected. It returns one of three possible formats:
MM/DD/YYYY
DD/MM/YYYY
YYYY/MM/DD
I'm not sure how you set your "Sat, 31 Dec 2011" format, but as far as I know stock Android allows to set only one of three mentioned formats (Settings -> Date and Time -> Select Date Format).
Try this
Date inDate = inFormat.parse(in);
DateFormat outFormat = android.text.format.DateFormat.getDateFormat(context);
out=outFormat.format(inDate);

Categories

Resources