private fun joinedDate(date: String): String {
val a = LocalDateTime.parse(
date,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
.withLocale(Locale.getDefault())
)
val date = "${a.month.toString().lowercase().replaceFirstChar { it.uppercase() }}, ${a.year}"
return date
}
This is my code i need to show month short name (e.g. Jan for January)
You can build and use a suitable DateTimeFormatter that only prints the short month-of-year, a comma and the year…
val dtfOut = DateTimeFormatter.ofPattern(
"MMM, uuuu", Locale.ENGLISH
)
… and then use it in the method LocalDateTime.format(DateTimeFormatter).
It will print the desired result if the object actually has a month-of-year and a year.
If you don't know the offset format, use a DateTimeFormatterBuilder in order to build up a maximally flexible DateTimeFormatter for parsing. Otherwise just use the one shown in your question.
Full example:
import java.util.Locale
import java.time.LocalDateTime
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatterBuilder
/*
define the output formatter
(short month, year, English)
*/
val dtfOut = DateTimeFormatter.ofPattern("MMM, uuuu", Locale.ENGLISH)
/*
prepare a formatter that is able to parse many
different offsets and no offset at all
*/
val dtfIn = DateTimeFormatterBuilder()
.optionalStart()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendOffsetId()
.optionalEnd()
.appendOptional(
DateTimeFormatter.ofPattern(
"uuuu-MM-dd'T'HH:mm:ss.SSSX"
)
)
.appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.toFormatter(Locale.ENGLISH);
// conversion method
private fun joinedDate(date: String): String {
// just parse, format and return
return LocalDateTime.parse(date, dtfIn)
.format(dtfOut)
}
// try with some different input values
fun main() {
val someDateTimes = listOf(
"2022-10-18T21:43:10.111+00",
"2022-10-18T21:43:10.111+0000",
"2022-10-18T21:43:10.111+00:00",
"2022-10-18T21:43:10.111Z",
"2022-10-18T21:43:10.111"
)
someDateTimes.forEach { println("${joinedDate(it)} <-- $it") }
}
Output:
Oct, 2022 <-- 2022-10-18T21:43:10.111+00
Oct, 2022 <-- 2022-10-18T21:43:10.111+0000
Oct, 2022 <-- 2022-10-18T21:43:10.111+00:00
Oct, 2022 <-- 2022-10-18T21:43:10.111Z
Oct, 2022 <-- 2022-10-18T21:43:10.111
Related
I have a working date picker in my app that replaces an EditText after a date selection. I want to add duration through a RadioGroup button that prints an Int to provoke an end date. How can I do that? I've spent the last two days without getting the result I'm looking to get.
Here is what I've got so far.
val datePicker = findViewById<DatePicker>(R.id.date_Picker)
val today = Calendar.getInstance()
datePicker.init(
today.get(Calendar.YEAR),
today.get(Calendar.MONTH),
today.get(Calendar.DAY_OF_MONTH
) { view, year, month, day ->
val month = month + 1
val startDay = ("$day-$month-$year")
binding.fechadeinicio.text = fechainicio
val duration = when (binding.duracion.checkedRadioButtonId) {
R.id.doce -> 12
R.id.veinticuatro -> 24
R.id.treintayseis -> 36
else -> 36
}
// val endDate = startDate.plusMonths(Duration.toLong())
// binding.endDate.text = endDate.toString()
}
Here is the closest one to the result I'm looking to get. Yet, I want to use the selected date val startDay, instead of val date = LocalDate.parse("2020-05-03"). When I replace it, the app crashes.
val date = LocalDate.parse("2020-05-03")
// Displaying date
println("Date : $date")
// Add 2 months to the date
val newDate = date.plusMonths(2)
println("New Date : $newDate")
Please, let me know how I can get the desired result?
Thanks.
I want to use the selected date that is val startDay instead of val date = LocalDate.parse("2020-05-03"). When I replace it, the app crashes.
val startDay = ("$day-$month-$year") here you've created date as dd-MM-yyyy, but by default LocalDate.parse uses DateTimeFormatter.ISO_LOCAL_DATE to parse a string, that parses a string of format yyyy-MM-dd to LocalDate. That's why it's crashing as your date is invalid according to that format.
You have to provide a DateTimeFormatter of pattern dd-MM-yyyy to parse your date.
You can do it like this
val startDay = ("$day-$month-$year")
val dateFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy")
binding.fechadeinicio.text = fechainicio
val duration = when (binding.duracion.checkedRadioButtonId) {
R.id.doce -> 12
R.id.veinticuatro -> 24
R.id.treintayseis -> 36
else -> 36
}
val startDate = LocalDate.parse(startDay, dateFormatter)
val endDate = startDate.plusMonths(duration.toLong()).format(dateFormatter)
binding.endDate.text = endDate
DatePicker returns year, month and day int values, now on creating date like val startDay = ("$day-$month-$year") would result in single digit for days and months less than 10, which would return 1 Jan 2020 as 1-1-2020 but date formatter is expecting it to be 01-01-2020.
To deal with this, we've to format int values before assigning it to the startDay, we can use format method of String to return 2 digits like this "%02d".format(intValue)
Change
val startDay = ("$day-$month-$year")
to
val startDay = "${"%02d".format(day)}-${"%02d".format(month)}-$year"
You can use LocalDate using of function.
Example here:
val date = LocalDate.of(year, month, day)
// Displaying date
println("Date : $date")
// Add 2 months to the date
val newDate = date.plusMonths(2)
println("New Date : $newDate")
i'm trying to get te selected date from DatePicker but always i have one day less than the selected
For example, if I select 14/2/2022 i obtain 13/2/2022 and if I select 8/10/2018 i obtain 7/10/2018
This is my code:
private fun DatePickerSelected() {
val picker = MaterialDatePicker.Builder.datePicker()
.setTitleText("Select date of birth")
.setSelection(MaterialDatePicker.todayInUtcMilliseconds())
.build()
picker.addOnPositiveButtonClickListener {
val date = Date(picker.selection!!)
Log.d("Date",date.toString())
val dateString = SimpleDateFormat("dd/MM/yyyy").format(date)
binding.edtBirthday.editText?.setText(dateString)
}
picker.show(requireActivity().supportFragmentManager, "BirthdayPicker")
}
Which is the problem? Thanks!
I found the solution using calendar
picker.addOnPositiveButtonClickListener {
val utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
utc.timeInMillis = it
//+1: The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0
val stringData = "${utc.get(Calendar.DAY_OF_MONTH)}/${utc.get(Calendar.MONTH)+1}/${utc.get(Calendar.YEAR)}"
binding.edtBirthday.editText?.setText(stringData)
}
try this code, add one day
date.add(Calendar.DAY_OF_MONTH,1)
This question already has answers here:
Add colon to 24 hour time in Java?
(7 answers)
Closed 1 year ago.
My input in this case is 2012-09-28 but I receive
01/01/2011 I would like to receive 09/28/2012
main(){
val scan = Scanner(System.`in`)
val originalFormat: DateFormat = SimpleDateFormat("YYYY-MM-DD", Locale.ENGLISH)
val targetFormat: DateFormat = SimpleDateFormat("MM/DD/YYYY")
val date = originalFormat.parse(scan.next())
val formattedDate = targetFormat.format(date)
println(formattedDate)
}
What is my code missing?
The modern API for parsing and formatting date and time is java.time, which was introduced with Java 8. You can either import the ThreeTenAbp or use Android API Desugaring in order to make it work in Android API versions below 26.
The following example uses java.time and considers the input of the two different formats you posted (one in your question and one as a comment to the first answer).
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Scanner
fun main() {
val scan = Scanner(System.`in`)
// create a formatter that parses the two different EXPECTED input formats
val inputFormatter = DateTimeFormatter.ofPattern("[uu-MM-dd][uuuu-MM-dd]");
// parse the input
val localDate: LocalDate = LocalDate.parse(scan.next(), inputFormatter)
// define a formatter with the desired output format
val targetFormat: DateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/uuuu")
// then create a String with the desired output format
val formattedDate: String = localDate.format(targetFormat)
// and print it
println(formattedDate)
}
The result for the inputs 12-09-30 or 2012-09-30 is 09/30/2012 in both cases.
Colud you try this way?
fun main() {
val scan = Scanner(System.`in`)
val originalFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
val targetFormat = SimpleDateFormat("MM/dd/yyyy")
val date = originalFormat.parse(scan.next())
val formattedDate = targetFormat.format(date)
println(formattedDate)
}
d is a day in the month. (ex_10)
D is a day in the year. (ex_189)
y is the year. (ex_1996; 96)
Y is week year. (ex_2009; 09)
Use yyyy instead of YYYY and dd instead of DD.
DD is the day of year while dd is the day of month.
YYYY is the week year and yyyy is the regular year.
https://developer.android.com/reference/java/text/SimpleDateFormat?hl=en
I want to create a function that returns a list of dates in the given range, with recursion. I will provide the starting date, the ending date, and the type of recursion. I am not sure how to start. Any suggestions would be helpful. Is there any library for this, or do I have to do it on my own?
data class Date(
val day: Int,
val month: Int,
val year: Int
)
enum class Recursion {
NEVER,
EVERY_DAY,
EVERY_WORK_DAY,
EVERY_WEEK,
EVERY_MONTH,
ANNUAL
}
fun createListOfEvents(startDate: Date, endDate: Date, recursion: Recursion): List<Date>{
}
You need to enable desugaring if targeting SDK < 26.
Then you can use the LocalDate class for this. Your Date class is kind of redundant, but you could convert inside the function to LocalDate if you want to keep it.
fun createListOfEvents(startDate: LocalDate, endDate: LocalDate, recursion: Recursion): List<LocalDate> {
val step = when (recursion) {
Recursion.NEVER -> return emptyList()
Recursion.EVERY_DAY, Recursion.EVERY_WORK_DAY -> Period.ofDays(1)
Recursion.EVERY_WEEK -> Period.ofWeeks(1)
Recursion.EVERY_MONTH -> Period.ofMonths(1)
Recursion.ANNUAL -> Period.ofYears(1)
}
var date = startDate
val list = mutableListOf<LocalDate>()
while (date <= endDate) {
list.add(date)
date += step
}
if (recursion == Recursion.EVERY_WORK_DAY) {
val weekend = listOf(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)
list.removeAll { it.dayOfWeek in weekend }
}
return list
}
Well, basically this is an example of how you can do this:
data class Recursion(val field : TemporalUnit, val step: Long)
val step1Day = Recursion(field = ChronoUnit.DAYS, step = 1)
fun createListOfEvents(startDate: LocalDate, endDate: LocalDate, recursion: Recursion): List<LocalDate>{
var currentDate = startDate
val listOfDates = mutableListOf<LocalDate>()
while (currentDate.isBefore(endDate)) {
listOfDates.add(currentDate)
currentDate = startDate.plus(recursion.step, recursion.field)
}
return listOfDates
}
This method returns list of dates from startDate until endDate with the step of Recursion.
As you can see I've used java.time.* classes for this, but eventually you can convert them into your own Date and Recursion and back.
Here TemporalUnit can be DAYS, WEEKS, MONTHS, YEARS (and other).
It covers most of your needs, working days you will have to manage manually.
Hope this makes sense )
I believe this question and answer explains how to format time series data into readable date labels in Java. How do you do the same thing in Kotlin?
You could create a custom formatter class extending the IAxisValueFormatter:
class MyCustomFormatter() : IAxisValueFormatter
{
override fun getFormattedValue(value: Float, axis: AxisBase?): String
{
val dateInMillis = value.toLong()
val date = Calendar.getInstance().apply {
timeInMillis = dateInMillis
}.time
return SimpleDateFormat("dd MMM", Locale.getDefault()).format(date)
}
}
Then assign it to your chart with
chart?.xAxis?.valueFormatter = MyCustomFormatter()
Using version 3.0+ of the MPAndroidChart:
Set formatter to the x axis:
// Formatter to adjust epoch time to readable date
lineChart.xAxis.valueFormatter = LineChartXAxisValueFormatter()
Create a new class LineChartXAxisValueFormatter:
class LineChartXAxisValueFormatter : IndexAxisValueFormatter() {
override fun getFormattedValue(value: Float): String? {
// Convert float value to date string
// Convert from seconds back to milliseconds to format time to show to the user
val emissionsMilliSince1970Time = value.toLong() * 1000
// Show time in local version
val timeMilliseconds = Date(emissionsMilliSince1970Time)
val dateTimeFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault())
return dateTimeFormat.format(timeMilliseconds)
}
}
When the entries are added to the ChartDataArray they are added in seconds, not milliseconds, to avoid potential precision issues with inputting as a float (i.e. milliseconds divided by 1000).
chartDataArray.add(Entry(secondsSince1970.toFloat(), yValue.toFloat()))
Happy coding!