0

I am developing news and in my adapter class I am getting below exception

Edgar, [20.10.19 13:50]

java.time.format.DateTimeParseException: Text '20/10/2019' could not be parsed at index 0 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1948) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) at java.time.LocalDateTime.parse(LocalDateTime.java:486) at java.time.LocalDateTime.parse(LocalDateTime.java:471) at yodgorbek.komilov.musobaqayangiliklari.adapter.BBCSportAdapter.onBindViewHolder(BBCSportAdapter.kt:83) at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781) at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823) at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752) at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854) at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230) at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557) at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517) at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612) at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924) at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3336) at android.view.View.measure(View.java:22260) at androidx.constraintlayout.widget.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227) at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1572) at android.view.View.measure(View.java:22260) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6686) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:22260) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6686) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:22260) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6686) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143) at android.view.View.measure(View.java:22260) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6686) at androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:403) at android.view.View.measure(View.java:22260) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6686) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:22260) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6686) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514) at android.widget.LinearLayout.measureVertical(LinearLayout.java:806) at android.widget.LinearLayout.onMeasure(LinearLayout.java:685) at android.view.View.measure(View.java:22260) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6686) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at com.android.internal.policy.DecorView.onMeasure(DecorView.java:728) at android.view.View.measure(View.java:22260) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2569) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1594) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1862) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1482) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7124) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1008) at android.view.Choreographer.doCallbacks(Choreographer.java:804) at android.view.Choreographer.doFrame(Choreographer.

below MyAdapter class

class BBCSportAdapter(private val context: Context) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    var articleList: List<Article> = listOf()
    companion object {
        const val urlKey = "urlKey"
        const val imageUrl = "imageUrl"
    }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.bbc_sport_item, null)
        return ViewHolder(view)
    }

    @SuppressLint("NewApi")
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

        (holder as ViewHolder).apply {
            when(position){
                0 -> {
                    header.visibility = ViewGroup.VISIBLE
                    item.visibility = ViewGroup.GONE

                    Picasso.get().load(articleList[position].urlToImage)
                        .into(bigImage)
                }
                else -> {
                    header.visibility = ViewGroup.GONE
                    item.visibility = ViewGroup.VISIBLE

                    articleTitle.text = articleList[position].title
                    articleSourceName.text = articleList[position].source.name
                    Picasso.get().load(articleList[position].urlToImage).into(image)
                    val input = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.getDefault())
                    val output = SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())
                    var d = Date()
                    try {
                        d = input.parse(articleList[5].publishedAt)
                    } catch (e: ParseException) {
                        try {
                            val fallback = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault())
                            fallback.timeZone = TimeZone.getTimeZone("UTC")
                            d = fallback.parse(articleList[5].publishedAt)
                        } catch (e2: ParseException) {
                            // TODO handle error
                            val formatted = output.format(d)
                            val timelinePoint = LocalDateTime.parse(formatted)
                            val now = LocalDateTime.now()

                            val elapsedTime = Duration.between(timelinePoint, now)

                            println(timelinePoint)
                            println(now)
                            elapsedTime.toMinutes()

                            articleTime.text = "${elapsedTime.toMinutes()}"

                            holder.itemView.setOnClickListener { v->
                                val intent = Intent(v.context, DetailActivity::class.java)
                                intent.putExtra("urlKey", articleList[position].url)
                                intent.putExtra("imageUrl", articleList[position].urlToImage)
                                v.context.startActivity(intent)
                            }
                        }
                    }
                }
            }
        }
    }
    override fun getItemCount(): Int {
        return articleList.size
    }

    fun setMovieListItems(articleList: List<Article>) {
        this.articleList = articleList
        notifyDataSetChanged()
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val image: ImageView = itemView.imageView
        val articleTitle: TextView = itemView.articleTitle
        val articleSourceName: TextView = itemView.articleSourceName
        val imageCategory: ImageView = itemView.imageCategory
        val articleTime: TextView = itemView.articleTime

        val bigImage = itemView.bigImage
        val header: CardView = itemView.header
        val item: CardView = itemView.item
    }
}

below Fragment class

class BBCSportFragment : Fragment() {

    private val listViewType: List<Int> = listOf()

    var bbcSportAdapter : BBCSportAdapter? = null




    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_sport_bbc, container, false)

        val recyclerView = view.findViewById (R.id.recyclerView) as RecyclerView
        bbcSportAdapter = BBCSportAdapter(recyclerView.context)

        recyclerView.layoutManager = LinearLayoutManager(context)
        recyclerView.adapter = bbcSportAdapter


        val apiInterface = SportNewsInterface.create().getBBCSport()

// Getting interface
        apiInterface.enqueue(object : Callback<SportNewsResponse> {
            override fun onResponse(
                call: Call<SportNewsResponse>?,
                response: Response<SportNewsResponse>?
            ) {

                if (response!!.body() != null) {
                    bbcSportAdapter!!.setMovieListItems(response.body()!!.articles)
                }
            }

            override fun onFailure(call: Call<SportNewsResponse>?, t: Throwable?) {

            }
        })


        return view
    }

}
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Edgar
  • 860
  • 1
  • 17
  • 38
  • 1
    Why the upvote? Is there a way that this question might be useful for other readers? – Ole V.V. Oct 21 '19 at 15:12
  • 1
    I know that [creating a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) is not something we can do from birth. I recommend that you train you ability. Your questions will be received better and most importantly, will get more good answers. – Ole V.V. Oct 21 '19 at 16:27
  • Do not [post repeatedly](https://stackoverflow.com/q/58294478/642706). If your Question is not met with a suitable Answer, revise that Question to clarify and focus. Strip your example code down to the bare minimum. – Basil Bourque Oct 21 '19 at 19:24
  • Possible duplicate of [java.time.format.DateTimeParseException: Text '09/10/2019' could not be parsed at index 0 could not be parsed, unparsed text found at index 19](https://stackoverflow.com/questions/58294478/java-time-format-datetimeparseexception-text-09-10-2019-could-not-be-parsed-a) – Basil Bourque Oct 21 '19 at 19:25

1 Answers1

0

The way I read your code you are receiving a publishedAt string that is supposed to look like 2019-10-21T15:12:34+02 or 2019-10-21T13:01:23Z. If you cannot parse it, your code is trying to use the date and time obtained from var d = Date() instead, that is, the current time.

java.time

It can be done very easily when you know how. I am sorry that I can write only Java code. I need to trust you to translate yourself.

    String publishedAt = "2019-10-21T13:01:23Z";
    Instant timelinePoint;
    try {
        timelinePoint = DateTimeFormatter.ISO_OFFSET_DATE_TIME
                .parse(publishedAt, Instant::from);
    } catch (DateTimeParseException dtpe) {
        timelinePoint = Instant.now();
    }

    Instant now = Instant.now();

    Duration elapsedTime = Duration.between(timelinePoint, now);

    System.out.println(timelinePoint);
    System.out.println(now);
    System.out.println(elapsedTime.toMinutes());

When I ran this snippet just now, I got this output:

2019-10-21T13:01:23Z
2019-10-21T16:17:49.719Z
196

DateTimeFormatter.ISO_OFFSET_DATE_TIME will parse your string the same no matter if the offset is given as hours and optional minutes or it is given as Z for zero. So the above handles both of your formats.

What went wrong in your code?

There is no reason whatsoever to bring SimpleDateFormat and Date into your code too. It will only make things more complex with nothing gained. Also those classes are poorly designed, the former in particular notoriously troublesome, and also long outdated, so I strongly recommend that you weed them out and never touch them again.

The LocalDateTime class from java.time that you are using is not the right class for a point on the time line. If the offset in your string differs from the UTC offset of your JVM’s default time zone, you will get LocalDateTime objects with different implied offsets. This means that it doesn’t make sense to compare them and you will get an incorrect elapsed time between them.

For the exception that you observed: In the case where you could not parse your string in either attempt, you were formatting the current date and time (from Date()) into the format dd/MM/yyyy, for example 21/10/2019, and then trying to parse this string using the one-arg LocalDateTime.parse(). There are a couple of things wrong with this. First, the parse method expects ISO 8601 format. The documentation says:

Obtains an instance of LocalDateTime from a text string such as 2007-12-03T10:15:30.

You see that the formats 21/10/2019 and 2007-12-03T10:15:30 are not the same. This is the reason for your exception. The exception message says at index 0 because at index 0 in your string is a two-digit number, and the method expects “four digits or more for the year” (quoted from the documentation of DateTimeFormatter.ISO_LOCAL_DATE). Second you don’t want to measure elapsed time in minutes based on a date with no time of day. Third you cannot parse a date string without time of day into a LocalDateTime (there are tricks to do it, but it doesn’t work just like that).

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • I was trying to tell you a few of the same pieces of information in [this answer](https://stackoverflow.com/a/58305083/5772882), sorry that it seems I wasn’t able. I have tried to spell out the explanation a little more this time, I hope it helps. – Ole V.V. Oct 21 '19 at 16:21