Problem converting Long to Time. Kotlin Android - android

Hello everybody. I have a project about the weather. And I am facing conversion problem, I am getting sunrise and sunset to Long (seconds) and I need to convert to HH: mm. When I run the application, I get invalid data, sunrise: 23:30 and sunset: 14:42. Although, in fact, we have sunrise at 5:30, sunset at 20:42. I can see a difference of 6 hours since we live in UTC +6 timezone, could this be related? how to convert correctly? my transform function
:
fun Long?.format(pattern: String? = "dd/MM/yyyy"): String{
this?.let {
val sdf = SimpleDateFormat(pattern, Locale.getDefault())
return sdf.format(Date(this * 1000))
}
return ""
}
mainactivity code
private fun setValuesToViews(it: ForeCast) {
val tvTemperature = findViewById<TextView>(R.id.tv_temperature)
val tvDate = findViewById<TextView>(R.id.tv_date)
val tvTempMax = findViewById<TextView>(R.id.tv_temp_max)
val tvTempMin = findViewById<TextView>(R.id.tv_temp_min)
val tvFeelsLike = findViewById<TextView>(R.id.tv_feels_like)
val tvWeather = findViewById<TextView>(R.id.tv_weather)
val tvSunrise = findViewById<TextView>(R.id.tv_sunrise)
val tvSunset = findViewById<TextView>(R.id.tv_sunset)
val tvHumidity = findViewById<TextView>(R.id.tv_humidity)
tvTemperature.text = it.current?.temp?.toString()
tvDate.text = it.current?.date.format()
tvTempMax.text = it.daily?.get(0)?.temp?.max?.roundToInt()?.toString()
tvTempMin.text = it.daily?.get(0)?.temp?.min?.roundToInt()?.toString()
tvFeelsLike.text = it.current?.feels_like?.roundToInt()?.toString()
tvWeather.text = it.current?.weather?.get(0)?.description
tvSunrise.text = it.current?.sunrise.format("hh:mm")
tvSunset.text = it.current?.sunset.format("hh:mm")
tvHumidity.text = "${it.current?.humidity?.toString()} %"
}

java.time
Consider using java.time, the modern Java date and time API, for your time work. I am sorry that I can write only Java. I am first defining a formatter for your desired time format:
private static final DateTimeFormatter TIME_FORMATTER
= DateTimeFormatter.ofPattern("HH:mm");
Formatting includes conversion to your time zone. Please substitute the correct time zone ID if it didn’t happen to be Asia/Urumqi.
// Example time zone at offset +06:00
ZoneId zone = ZoneId.of("Asia/Urumqi");
long sunriseLong = 1_625_700_600;
long sunsetLong = 1_625_755_320;
Instant sunrise = Instant.ofEpochSecond(sunriseLong);
System.out.println(sunrise);
String sunriseText = sunrise.atZone(zone).format(TIME_FORMATTER);
System.out.println(sunriseText);
Instant sunset = Instant.ofEpochSecond(sunsetLong);
System.out.println(sunset);
String sunsetText = sunset.atZone(zone).format(TIME_FORMATTER);
System.out.println(sunsetText);
Output is:
2021-07-07T23:30:00Z
05:30
2021-07-08T14:42:00Z
20:42
I have also printed the Instant objects that I use. These print in UTC, and you recognize the invalid times 23:30 and 14:42. After converting to your time zone the times are correct.
Your weather data may also include information about UTC offset that you may use instead of defining the time zone yourself. You could check. An example:
int timezone = 21600;
ZoneOffset offset = ZoneOffset.ofTotalSeconds(timezone);
System.out.println(offset);
String sunriseText = sunrise.atOffset(offset).format(TIME_FORMATTER);
System.out.println(sunriseText);
+06:00
05:30
I only printed the offset as confirmation that I have interpreted the number, 21600, correctly. The expected sunrise time of 05:30 is printed again. Sunset goes in the same way, as you may have guessed already.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
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.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.

Related

SimpleDateFormat indicates 2 more hours

I have this code , but it gives 2 more hours
val leftTimeInMillis = 12728918
val mTimeFormat = SimpleDateFormat("HH:mm:ss", Locale.ROOT)
binding.textTimeLeft.text = mTimeFormat.format(leftTimeInMillis)
Normally the text must be indicate 03:32:08 but it is 05:32:08
java.time.Duration through desugaring and String.format()
Use java.time, the modern Java date and time API, for your time work.
I haven’t got an Android development environment, but I expect the following to work with desugaring (see the link below). It works with desktop Java version 9 and later.
int leftTimeInMillis = 12_728_918;
Duration timeLeft = Duration.ofMillis(leftTimeInMillis);
String formattedTimeLeft = String.format("%02d:%02d:%02d",
timeLeft.toHours(), timeLeft.toMinutesPart(), timeLeft.toSecondsPart());
System.out.println(formattedTimeLeft);
Output is the required:
03:32:08
If for some reason instead of desugaring your are using ThreeTenABP, I believe that the toMinutesPart and toSecondsPart methods are not included. Then the conversion takes a little bit more:
Duration timeLeft = Duration.ofMillis(leftTimeInMillis);
long hours = timeLeft.toHours();
timeLeft = timeLeft.minusHours(hours);
long minutes = timeLeft.toMinutes();
timeLeft = timeLeft.minusMinutes(minutes);
long seconds = timeLeft.getSeconds();
String formattedTimeLeft = String.format("%02d:%02d:%02d",
hours, minutes, seconds);
Output is the same as before.
Alternative: Time4A
If you’re happy with an extensive external library for date and time, an option is Time4A, the Android version of Time4J. It offers a solution that is a bit more elegant and more in line with what you tried yourself. I prefer to declare a static formatter:
private static final Duration.Formatter<ClockUnit> M_TIME_FORMAT
= Duration.formatter(ClockUnit.class, "hh:mm:ss");
Now formatting goes like:
int leftTimeInMillis = 12_728_918;
Duration<ClockUnit> timeLeft = Duration.of(leftTimeInMillis, ClockUnit.MILLIS)
.with(Duration.STD_CLOCK_PERIOD);
String formattedTimeLeft = M_TIME_FORMAT.format(timeLeft);
System.out.println(formattedTimeLeft);
03:32:08
Again I have developed my code on desktop Java using Time4J.
What went wrong in your code?
What happened in your code? Where did those 2 hours come from? SimpleDateFormat was designed in the 1990’s and was always for formatting and parsing a point in time, never an amount of time. So it takes your number, 12 728 918, to mean a point in time this many milliseconds after the Java epoch of Jan 1 1970 at start of day in UTC. In other words you are trying to format an instant of 1970-01-01T03:32:08.918Z. Since the time zone setting of your device (a guess would be Europe/Athens) was 2 hours ahead of UTC in the winter of 1970, the date and time used for formatting is 1970-01-01T05:32:08.918+02:00[Europe/Athens]. Which is why you got 05:32:08.
Assuming that you did not have a time in New Year’s night in 1970 in mind, what you are doing is wrong, and even if you could make it work, it will confuse everyone reading your code. Also if one day the anount of milliseconds exceeds 24 hours, the whole days will not be printed, probably causing great confusion. Don’t use SimpleDateFormat for this purpose. And consider never using SimpleDateFormat at all since that class is notoriously troublesome and long outdated.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
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.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Time4A on GitHub
I know its a late answer
But try setting the GMT's offset for the SimpleDateFormat to "GMT+0", for me I'm using this method to get the time left for a timeStamp, and it's working as expected:
private fun getTimeString(
timeStamp: Long,
isShowHoursEventItsZero: Boolean = false,
isShowMillis: Boolean = false,
locale: Locale = Locale.ENGLISH,
): String {
var mainFormat = "mm:ss"
if (TimeUnit.MILLISECONDS.toHours(timeStamp) > 0 || isShowHoursEventItsZero) {
mainFormat = mainFormat.prependIndent("HH:")
}
if (isShowMillis) {
mainFormat = mainFormat.plus(".SS")
}
val dateFormat = SimpleDateFormat(mainFormat, locale)
dateFormat.timeZone = TimeZone.getTimeZone("GMT+0")
return dateFormat.format(Date(timeStamp))
}

Display time interval in minutes using joda Date time to display in Calendar

I want to display list of time interval with 15 minutes or 30 minutes like
like
1:00
1:15
1:30
1:45
or
1:00
1:30
2:00
2:30
below code is using Joda Date time library and it's showing time with interval of hours . I simply want to display time with interval of 15 or 30 minutes .
val hourDateTime = DateTime().withDate(2000, 1, 1).withTime(0, 0, 0, 0)
for (i in 1..23) {
val formattedHours = Formatter.getHoursWithMinutes(context!!, hourDateTime.withHourOfDay(i))
}
Formatter.kt
fun getHoursWithMinutes(context: Context, dateTime: DateTime) = dateTime.toString("h:mm a")
Instead of showing date(s) like 1:00 ,2:00 ,3:00 ,4:00 display with interval of 15 or 30 minutes
Currently working View which is working using Simple Calendar
I have tried another approach written below but this time time interval changes but hours remain same like
12:00 -> 12:30 -> 12:00 -> 12:30
val hourDateTime = DateTime().withDate(2000, 1, 1).withTime(0, 0, 0, 0)
var interval = 30
for (i in 1..23) {
if(i == 1 ) interval = 0
val formattedHours = Formatter.getHoursWithMinutes(context!!, hourDateTime.withMinuteOfHour(interval) )
interval += 30
if(interval == 60) interval = 0
}
java.time and ThreeTenABP
I can’t write Kotlin. Please translate from my Java.
Duration interval = Duration.ofMinutes(15);
LocalTime time = LocalTime.of(1, 0);
for (int i = 0; i < 10; i++) {
System.out.println(time);
time = time.plus(interval);
}
Output:
01:00
01:15
01:30
01:45
02:00
02:15
02:30
02:45
03:00
03:15
Set the interval to Duration.ofMinutes(30) to get 01:00, 01:30, etc.
I am using java.time, the modern Java date and time API, through the backport, see below. java.time is the successor of Joda-Time. I am sure something very similar to the above is possible with Joda-Time too in case you are already using Joda-Time and don’t want to migrate to java.time just now.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
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.time to 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.

Text Recognizer from image to find the date

In my app I need a help to find the date from image using Text Recognizer.
But in image the date can be in any format such as:
dd/mm/yyyy, dd-mm-yyyy, dd mm yyyy, dd mmm yyyy, dd-mmm-yyyy, dd/mmm/yyyy etc.
Dependencies:
implementation "com.google.android.gms:play-services-vision:18.0.0"
Code:
TextRecognizer mText = new TextRecognizer.Builder(getApplicationCOntext()).build();
if(mText.isOperational()) {
readText(bitmap,mtext);
}
private void readText(Bitmap bitmap, TextRecognizer mTextRecognizer) {
if(bitmap != null) {
Frame mframe = new Frame.Builder().setBitmap(bitmap).build();
SparseArray<TextBlock> mTextBlockSparseArray = mTextRecognizer.detect(mframe);
StringBuilder mStringBuffer = new StringBuilder();
}
}
How to get the DATE from the image?
String.replaceFirst() and java.time through ThreeTenABP
There are some different ways to go about it. I present a kind of mixed approach: I am using a regular expression for the different possible delimiters, which validates that both delimiters (after day and after month) are the same. Next I am using optional parts in the format pattern string to handle month as either abbreviation (Jan) or number (01).
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-[MMM][MM]-uuuu", Locale.ENGLISH);
String[] inputs = { "02/01/2020", "04-01-2020", "07 01 2020",
"09 Jan 2020", "13-Jan-2020", "17/Jan/2020" };
for (String input : inputs) {
String withHyphens = input.replaceFirst("([/ ])(.*)\\1", "-$2-");
LocalDate date = LocalDate.parse(withHyphens, dateFormatter);
System.out.format("%11s was parsed into %s%n", input, date);
}
Output from this smippet is:
02/01/2020 was parsed into 2020-01-02
04-01-2020 was parsed into 2020-01-04
07 01 2020 was parsed into 2020-01-07
09 Jan 2020 was parsed into 2020-01-09
13-Jan-2020 was parsed into 2020-01-13
17/Jan/2020 was parsed into 2020-01-17
If you prefer, you may also use optional parts in the format pattern string for everything. Then your format pattern may look like dd[/][-][ ][MMM][MM][/][-][ ]uuuu. It gives more lenient validation, but is more consistent and shorter.
I am using the backport of java.time, the modern Java date and time API.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
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.time to 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.

Get weekdays in order by locale

I'm trying to see if we can get the weekdays in order by locale. For example in US locale, we'll start with Sunday, while FR will start with Monday (in the terms of Calendar). To make sense out of it, I'm making an alarm app with the weekdays where the alarm is repeated on certain days -
Here are weekdays are not in ordered that I'm seeing in
new DateFormatSymbols().getShortWeekdays();
0 = ""
1 = "Sun"
2 = "Mon"
3 = "Tue"
4 = "Wed"
5 = "Thu"
6 = "Fri"
7 = "Sat"
0 = ""
1 = "dim."
2 = "lun."
3 = "mar."
4 = "mer."
5 = "jeu."
6 = "ven."
7 = "sam."
java.time
public static void printWeekdays(Locale loc) {
WeekFields wf = WeekFields.of(loc);
DayOfWeek day = wf.getFirstDayOfWeek();
for (int i = 0; i < DayOfWeek.values().length; i++) {
System.out.println(day.getDisplayName(TextStyle.SHORT, loc));
day = day.plus(1);
}
}
Let’s try it out:
printWeekdays(Locale.US);
The output from this call is:
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Or in French:
printWeekdays(Locale.FRANCE);
Now Monday/lundi comes first, and in French, of course:
lun.
mar.
mer.
jeu.
ven.
sam.
dim.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
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.time to 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.

Android : how can I add 5 Times in a variable and get total seconds of them

like i have 5 Times
1. 05:12:02
2. 19:12:52
3. 40:12:14
4. 56:54:10
5. 41:12:12
-----------
Total Seconds : 0#####..`
-----------
i want like this, how can i , please help me .
can I use this? :
public String addTime(int hour, int minute, int minutesToAdd) {
Calendar calendar = new GregorianCalendar(1990, 1, 1, hour, minute);
calendar.add(Calendar.MINUTE, minutesToAdd);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
String date = sdf.format(calendar.getTime());
return date;
}
Use the Duration class from java.time (the modern Java date and time API):
String[] times = {
"05:12:02",
"19:12:52",
"40:12:14",
"56:54:10",
"41:12:12"
};
Duration timeSum = Duration.ZERO;
for (String time : times) {
// reformat to ISO 8601
time = time.replaceFirst("(\\d{2}):(\\d{2}):(\\d{2})", "PT$1H$2M$3S");
// add
timeSum = timeSum.plus(Duration.parse(time));
}
System.out.println("Total seconds: " + timeSum.getSeconds());
Output:
Total seconds: 585810
The Duration class cannot directly parse your time strings. It parses ISO 8601 standard format, so I use a regular expression for converting 05:12:02 to PT05H12M02S. Then I feed this into Duration.parse. You may read the ISO 8601 string as “a period of time of 05 hours 12 minutes 02 seconds”.
Classes meant for dates and times — Date, Calendar, LocalTime, etc. — are ill suited for amounts of time. Date and Calendar are furthermore long outdated and poorly designed, so don’t try those. While it wouldn’t be impossible to get through, there are some pitfalls, and even if you succeed, it will be hard to read the code and convince oneself that it is correct.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom). The code above was developed and run with org.threeten.bp.Duration from the backport.
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
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.time to 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.
Wikipedia article: ISO 8601
A easy way to do it, if the format is the one you have pointed, without have to worry in convert the Date is the following:
int totalSum = getSecondsFromDate("05:12:02") + getSecondsFromDate("19:12:52") + getSecondsFromDate("40:12:14") + getSecondsFromDate("56:54:10") + getSecondsFromDate("41:12:12");
private int getSecondsFromDate(String date){
//We split the date to have hours, minutes and seconds
String splitDate = date.split(":");
int hours = Integer.parseInt(splitDate[0]);
int minutes = Integer.parseInt(splitDate[1]);
int seconds = Integer.parseInt(splitDate[2]);
int totalSeconds = (hours*60*60) + (minutes*60) + seconds;
return totalSeconds;
}

Categories

Resources