How to format Ints from datePicker to date-string - android

I am able to get the date values from date picker:
override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
Log.i("onDateSet", year.toString())
Log.i("onDateSet", month.toString())
Log.i("onDateSet", dayOfMonth.toString())
}
How can I format this ints into date-string, something like this for example: 2020-05-05
And I saw that the month always returning one month ago, if today is 5th month, it's returning 4th month.
Is it a bug or I just how it works and I need to add 1 to every month I'm getting from date picker?

The doc says that month int: the selected month (0-11 for compatibility with Calendar#MONTH), so yeah, this is the desired behavior and to format it to human readable you have to add 1 I suppose.
And for formatting a string you should probably manually concat the data you have
val date = "$year-${month+1}-$day"
(the quickest way to me, but you may choose some prettier one)
Alternatively you could do:
val date = LocalDate(year, monthOfYear + 1, dayOfMonth).toString("yyyy-MM-dd")

As mentioned in the AndroidSDK's Date class,
A month is represented by an integer from 0 to 11; 0 is January, 1 is February, and so forth; thus 11 is December.
An hour is represented by an integer from 0 to 23. Thus, the hour from midnight to 1 a.m. is hour 0, and the hour from noon to 1 p.m. is hour 12.
A minute is represented by an integer from 0 to 59 in the usual manner.
A second is represented by an integer from 0 to 61; the values 60 and 61 occur only for leap seconds.
Date and Year are represented in the usual manner, while the things mentioned above are represented with their respective rule.
Hence if its May, it will return 4, if its June it will return 5, and so on.
NOTE: Although this behavior may seem strange, it is consistent with the java.util.Calendar class (although it is not consistent with joda.time.DateTime).

Related

How to parse 13-digit sqlite timestamp

The sqlite timestamp here is 13 digits, but how can one know its specific date. 1667458854391 should correspond to November 2022, but this year cannot be obtained regardless of interpretation or other conversions. I want to get time like 2022-11-03 15:00:54.
This method only works for ten digits
datetime('now','unixepoch', 'localtime')
This is sqllite timestamp, but product specific model does not know,only know that this timestamp is 13-digit just like these: 1667458854391 1667458752768
I tried to do this but it didn't feel compliant
datetime(substr(warehouse_inout_log.createTime,1,10),'unixepoch', 'localtime'),
The sqlite timestamp here is 13 digits, but how can one know its specific date.
You simply drop the 3 digits (the milliseconds) you do do this by dividing by 1000 or by using substring(createTime,1,10)
but this year cannot be obtained
If you want the year then you can use the strftime function with the %Y format String. e.g.
strftime('%Y',createTime/1000,'unixepoch','localtime')
I want to get time like 2022-11-03 15:00:54
What you have works. However it is simpler to use
datetime(createTime/1000,'unixepoch','localtime')
The following demonstrates the above (and also includes part of the official documentation regarding the formatting arguments):-
DROP TABLE IF EXISTS warehouse_inout_log;
CREATE TABLE IF NOT EXISTS warehouse_inout_log (createTime INTEGER);
INSERT INTO warehouse_inout_log VALUES
(1667458854391),(1667458752768),('1667458752768')
;
/*
The strftime() routine returns the date formatted according to the format string specified as the first argument. The format string supports the most common substitutions found in the strftime() function from the standard C library plus two new substitutions, %f and %J. The following is a complete list of valid strftime() substitutions:
%d day of month: 00
%f fractional seconds: SS.SSS
%H hour: 00-24
%j day of year: 001-366
%J Julian day number (fractional)
%m month: 01-12
%M minute: 00-59
%s seconds since 1970-01-01
%S seconds: 00-59
%w day of week 0-6 with Sunday==0
%W week of year: 00-53
%Y year: 0000-9999
%% %
*/
SELECT
strftime('%Y',createTime/1000,'unixepoch','localtime') AS createYear,
datetime(createTime/1000,'unixepoch','localtime') AS createDateTime,
strftime('%Y',substr(createTime,1,10),'unixepoch','localtime') AS createYearV2,
datetime(substr(createTime,1,10),'unixepoch','localtime') AS createDateTimeV2
FROM warehouse_inout_log
;
DROP TABLE IF EXISTS warehouse_inout_log;
Resulting in:-

How to get epoch milis from a date (LocalDate)

I have a month July 2022 for example, I want get epoch milis for the first day of the month
1st July 2022 at midnight.
from the month I was able to get the 1st July 2022, but how to convert it into epoch milis for 1st July 22 midnight
val datey = "July/2020"
val dateFormaty = DateTimeFormatter.ofPattern("MMMM/yyyy")
val yearMonthy = YearMonth.parse(datey, dateFormaty)
val parsedDatey = yearMonthy.atDay(1)
I get 2022-07-01 for parsedDate, I want to get the date time for this date in epoch milis
Thanks
R
Like I mentioned, LocalDate does not actually store any time information whatsoever, so transforming it to epoch isn't possible. Technically. Yet it is with some possible inacuracies.
How about something like this:
make the following extension function
fun LocalDate.toDate(): Date = Date.from(this.atStartOfDay(ZoneId.systemDefault()).toInstant())
Note that it uses the system default timezone for this, to provide the necessary information.
then just use it.
val myDate = myLocalDate.toDate()
which would in your case, be parsedDatey.toDate()
But, we don't really even need the Date here. Lets avoid casting the LocalDate to Date then getting the epoch milli from there, and just do it from the provided Instant instead.
So the real answer to your question is this:
fun LocalDate.getEpochMillis(): long = this.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli()
// call this in your parsing method you posted
parsedDatey.getEpochMillis()

Difference between 2 dates in days and in double

I am working on an app and i need to get the difference between the actual date and a date inserted by the user, in days and in double.
Any idea on how to make this? I've tried some things but without success.
First you must decide if you want to consider the time of the day and the timezone to calculate the difference, because this can lead to different results.
Example: current date (AKA "today") is April 17th or 18th, depending on where in the world you are. Actually, depending on the time of the day, there might be 3 different "todays" in the world, at the same time. What timezone are you using to calculate the difference?
the user will enter a date: only day, month and year? Will it enter the hours? Are you using the user's device's timezone or some specific zone?
the same questions apply to the current date
Depending on the choices you make, you might get a different result.
Anyway, I'd use this lib: http://www.threeten.org/threetenbp/
or java.time classes, if available in your API level. In both API's you can use the following.
To use a date (day-month-year only) and the device's default timezone, I'd choose the LocalDate class:
// current date in device's default timezone
LocalDate now = LocalDate.now();
// some date from input values (May 10th 2018)
LocalDate dt = LocalDate.of(2018, 5, 10);
// difference in days
long diff = ChronoUnit.DAYS.between(now, dt); // 23
If you want to consider the time of the day (hours, minutes, etc), use a LocalDateTime. But in this case, ChronoUnit.DAYS considers a day has passed when the time is >= the other (ex: the difference between April 17th at 10 AM and April 18th 9:59 AM is zero days, because the time of the day didn't reach 10 AM, so it didn't complete 1 day - with LocalDate this doesn't happen because this class doesn't have time-of-the-day fields and considers only the day, month and year).
If you want to consider everything (date, time, and timezone), including Daylight Saving Time transitions, use a ZonedDateTime instead (the code is very similar, the only difference is that you can choose a timezone to work with):
// current date/time in device's default timezone
ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault());
// some date from input values (May 10th 2018, 10 AM in New York timezone)
ZonedDateTime dt = ZonedDateTime.of(2018, 5, 10, 10, 0, 0, 0, ZoneId.of("America/New_York"));
// difference in days
long diff = ChronoUnit.DAYS.between(now, dt); // 23
You can choose between the device's default timezone (ZoneId.systemDefault()) or a specific one (ZoneId.of("America/New_York")). You can check all the available timezones with ZoneId.getAvailableZoneIds().
Maybe it doesn't make sense to use current date in one timezone and user's date in another (I'd use the same for both), but that's up to you to decide.
Calendar c = Calendar.getInstance();
Calendar c2 // = what you will get from the user
long diff = c.getTimeInMillis()-c2.
double days = (double) diff/(1000*60*60*24);
that is what i have in mind.
I hope this helps
use this way
public static double getTimeDiffBetweenDate(Date startDateTime, Date finishDateTime) {
long diffInMilliseconds = finishDateTime.getTime() - startDateTime.getTime();
return TimeUnit.MILLISECONDS.toMinutes(diffInMilliseconds) / 60.0;
}

Days difference between local date objects

LocalDate today=LocalDate.now();
And the event date is:
eventDate=LocalDate.of(year, monthOfYear,dayOfMonth); (from the date picker dialog)
I'm trying to calculate the days difference between them... The shortest thing I have found is this:
int DaysDifference = Period.between(eventToDisplay.getEventDate(),today).getDays();
While the first object is "today", and the second one is "eventToDisplay.getEventDate()." It didn't work for me, it showed the wrong number of days.
I have also tried to do it like this:
eventToDisplay.getEventDate().compareTo(today)
Also didn't work...
I have also tried to do it without joda-time, because I had troubles with it, because of what I'm trying to do with date and time...
The other things I have found are long and complicated, and I thought maybe there is a better way, without the joda-time.
EDIT:
I have just tried this:
Calendar now = Calendar.getInstance();
Calendar chosenDate=Calendar.getInstance();
chosenDate.set(eventToDisplay.getEventDate().getYear(),eventToDisplay.getEventDate().getMonth().getValue(),eventToDisplay.getEventDate().getDayOfMonth());
long def= chosenDate.getTimeInMillis() - now.getTimeInMillis();
long DaysDifference =TimeUnit.MILLISECONDS.toDays(def);
Didn't work for me
EDIT:
This has worked for me:
LocalDate today=LocalDate.now();
Calendar now = Calendar.getInstance();
now.set(today.getYear(),today.getMonthValue(),today.getDayOfMonth());
Calendar chosenDate=Calendar.getInstance();
chosenDate.set(eventToDisplay.getEventDate().getYear(),eventToDisplay.getEventDate().getMonthValue(),eventToDisplay.getEventDate().getDayOfMonth());
long def= chosenDate.getTimeInMillis() - now.getTimeInMillis();
long daysDifference =TimeUnit.MILLISECONDS.toDays(def);
you can use something like this:
Calendar now = Calendar.getInstance();
Calendar end=Calendar.getInstance();
end.set(<year>, <month>, <day>);
long def= end.getTimeInMillis() - now.getTimeInMillis();
long days =TimeUnit.MILLISECONDS.toDays(def);
java.time
Since you can use LocalDate from java.time, the modern Java date and time API, I warmly recommend that you stick to java.time. Calculating the difference is simple and straightforward when you know how:
LocalDate today = LocalDate.now(ZoneId.systemDefault());
LocalDate eventDate = LocalDate.of(2021, 5, 5);
long differenceDays = ChronoUnit.DAYS.between(today, eventDate);
System.out.println("Difference is " + differenceDays + " days.");
Output when I ran today (APril 18 in my tme zone):
Difference is 17 days.
If your date picker uses 0-based months (some date pickers insanely use 0 for January through 11 for December), remember to add 1 to the month number before passing it to LocalDate.
What went wrong in all your attempts?
int DaysDifference = Period.between(eventToDisplay.getEventDate(),today).getDays();
The Period class represents a period of years, months and days. Since months have different lengths, a Period does not correspond to any exact number of days, so it’s not the right class to use here. You tried to use its getDays method, which gives you the days component of the period, not the months or the years. So if the two days are less than a month apart, you will get the correct result, otherwise not. If for example the two dates are 1 month 3 days apart, you will only get the 3 days.
The Calendar class used in more than one of your attempts is poorly designed and long outdated. Counting days correctly with it would be truly cumbersome, so no wonder that your attempts gave the wrong results.
Both of your attempts are wrong for at least two reasons:
A Calendar has a date and a time of day. So by finding the difference in milliseconds and dividing by the number of milliseconds that you think are in a day, you will get different results depending on the time of day that happens to be in each of your Calendar objects. Your code calls Calendar.getInstance() twice. In an extreme situation your code may run across midnight so the time in the first Calendar will be close to 23:59:59 and in the second close to 00:00, which will almost certainly give you an error of 1 day.
A day is not always 24 hours. Summer time (DST) is the most frequent but not the only reason why a date is sometimes 23 hours, 25 hours or some other length. If for example you try to count days across the spring forward where a day is only 23 hours or 23 hours 30 minutes, your code will count 1 day too few.
Furthermore this line from the snippet that you say that works is definitely wrong:
now.set(today.getYear(),today.getMonthValue(),today.getDayOfMonth());
You are using the 1-based month number from LocalDate, for example 4 for April, as a 0-based month number in Calendar, for example 4 would mean May. So your Calendar is off by 1 month. Since I haven’t got your complete code, is may in some cases balance out by another error that causes the other Calendar to be 1 month off too, I cannot know. Since months have different lengths, you will still get an error of up to 3 days sometimes.

sqlite rounding 'error'

I'm using SQLite on and Android device.
I am attempting to convert a timestamp to a julian day, and round down the julian day by casting the result to an integer. For some reason, 2456902.0 is being rounded to 2456901. (I get the same result with the 'round' function as well)
I do need a workaround, but I would also like an explanation as to why this is happening if anyone has one.
My code and results are listed below:
cast(julianday((c.ts/1000), 'unixepoch') as int) as day,
julianday((c.ts/1000), 'unixepoch') as jd
When ts = 1409564846705, jd = 2456902.0, day = 2456901 (datetime is Mon Sep 01 04:47:26 CDT 2014)
When ts = 1409631153881, jd = 2456902.8, day = 2456902 (datetime is Mon Sep 01 23:12:33 CDT 2014)
I am trying to convert the timestamp to julian days to group records by day, but some data is falling into the wrong day (as you can see above, two records will be produced if I group by day, but the dates are part of the same day). I've resorted to: strftime('%d', datetime((c.ts/1000), 'unixepoch', 'localtime')) as day. The problem with this is that if I query for more than a month, there will be duplicate 'day of month's. Is there a better way to do this?
Julian day numbers have integer values at noon, so the start of a day is halfway between integers:
> SELECT julianday(1409631153881/1000, 'unixepoch', 'start of day');
2456902.5
It does not make sense to round Julian day numbers to integers unless you define precisely whether you want the previous or the next noon.
If you want just to group by the day, convert the value into a date string:
date(c.ts / 1000, 'unixepoch', 'localtime')
If you want a value that can be converted into a number, combine the year and the day of the year:
cast(strftime('%Y%j', c.ts / 1000, 'unixepoch', 'localtime') as int)
Alternatively, just divide the timestamp by the number of milliseconds in a day, but then you need to substract the proper offset of the timezone.

Categories

Resources