java.time.format.DateTimeParseException: текст «20/10 / 2019» не может быть проанализирован с индексом 0 - PullRequest
0 голосов
/ 20 октября 2019

Я занимаюсь разработкой новостей и в своем классе адаптеров получаю исключение ниже

Эдгар, [20.10.19 13:50]

java.time.format.DateTimeParseException:Текст '20 / 10/2019 'не может быть проанализирован с индексом 0 в java.time.format.DateTimeFormatter.parseResolved0 (DateTimeFormatter.java:1948) в java.time.format.DateTimeFormatter.parse (DateTimeFormatter.java:1851) вjava.time. .recyclerview.widget. .java: 5752) at androidx.recyclerview.widget.RecyclerView $ Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java: 6019) по адресу androidx.recyclerview.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.java:5858) по адресу androidx.recyclerview.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.java:5854) по адресу androidx.regetanar.ar$ LayoutState.next (LinearLayoutManager.java! widget.LinearLayoutManager.onLayoutChildren (LinearLayoutManager.java:612) в androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2 (RecyclerView.java:3924) в androidx.recyclerview.widget.MacViewView: Recycleler (androidView).View.measure (View.java:22260) в androidx.constraintlayout.widget.ConstraintLayout.internalMeasureChildren (ConstraintLayout.java:1227) в androidx.constraintlayout.widget.ConstraintLayout.onMeasure (ConstraintLayout.j72) и javaroid.view.View.measure (View.java:22260) в android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6686) в android.widget.FrameLayout.onMeasure (FrameLayout.java:185) в android.view.View.measure (View.java:22260) в android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6686) в android.widget.FrameLayout.onMeasure (FrameLayout.java:185) в android.view.View.measure (Просмотреть. Java: 22260) на android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6686) на android.widget.FrameLayout.onMeasure (FrameLayout.java:185) на androidx.appcompat.widget.ContentFrameLayout.jme3 (14)) в android.view.View.measure (View.java:22260) в android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6686) в androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure (ActionBarOverlayLayout.java:40).view.View.measure (View.java:22260) в android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6686) в android.widget.FrameLayout.onMeasure (FrameLayout.java: 185) на android.view.View.measure (View.java:22260) на android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6686) на android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java:15)android.widget.LinearLayout.measureVertical (LinearLayout.java:806) в android.widget.LinearLayout.onMeasure (LinearLayout.java:685) в android.view.View.measure (View.java:22260) в android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6686) в android.widget.FrameLayout.onMeasure (FrameLayout.java:185) в com.android.internal.policy.DecorView.onMeasure (DecorView.java:728) в android.view.View. измерение (View.java:22260) в android.view.ViewRootImpl.performMeasure (ViewRootImpl.java:2569) в android.view.ViewRootImpl.measureHierarchy (ViewRootImpl.java:1594) вandroid.view.ViewRootImpl.performTraversals (ViewRootImpl.java:1862) в android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:1482) в android.view.ViewRootImpl $ TraversalRunnable.run (ViewRo): atv. .Choreographer $ CallbackRecord.run (Choreographer.java:1008) на android.view.Choreographer.doCallbacks (Choreographer.java:804) на android.view.Choreographer.doFrame (Хореограф.

* 1008 нижекласс
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
    }
}

ниже Фрагмент класса

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
    }

}

1 Ответ

0 голосов
/ 21 октября 2019

При чтении вашего кода вы получаете строку publishedAt, которая должна выглядеть как 2019-10-21T15:12:34+02 или 2019-10-21T13:01:23Z. Если вы не можете разобрать его, ваш код пытается использовать вместо него дату и время, полученные из var d = Date(), то есть текущее время.

java.time

Это можно сделать оченьлегко, когда знаешь как. Мне жаль, что я могу писать только код Java. Мне нужно доверять вам, чтобы перевести себя.

    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());

Когда я только что запустил этот фрагмент, я получил такой вывод:

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

DateTimeFormatter.ISO_OFFSET_DATE_TIME будетразбирать вашу строку одинаково, независимо от того, задано ли смещение в виде часов и необязательных минут или в виде Z для нуля. Таким образом, вышеприведенное относится к обоим вашим форматам.

Что пошло не так в вашем коде?

Нет никаких причин вводить SimpleDateFormat и Date в ваш код. Это только усложнит ситуацию, ничего не выиграв. Кроме того, эти классы плохо разработаны, первые, в частности, печально известны своими хлопотами, а также давно устарели, поэтому я настоятельно рекомендую вам отсеять их и никогда больше не трогать.

Класс LocalDateTime из java.time, которыйвы используете неправильный класс для точки на временной шкале. Если смещение в вашей строке отличается от смещения UTC для часового пояса JVM по умолчанию, вы получите LocalDateTime объектов с различными подразумеваемыми смещениями. Это означает, что не имеет смысла сравнивать их, и вы получите неверное истекшее время между ними.

За исключением того, что вы наблюдали: В случае, когда вы не могли разобрать вашу строку в любой попытке,Вы форматировали текущую дату и время (с Date()) в формат dd/MM/yyyy, например 21/10/2019, а затем пытались проанализировать эту строку, используя одно аргумент LocalDateTime.parse(). Есть несколько вещей не так с этим. Во-первых, метод parse предполагает формат ISO 8601. Документация гласит:

Получает экземпляр LocalDateTime из текстовой строки, такой как 2007-12-03T10:15:30.

Вы видите, что форматы 21/10/2019 и 2007-12-03T10:15:30 не одинаковы. Это причина вашего исключения. Сообщение об исключении говорит at index 0, потому что в индексе 0 в вашей строке есть двузначное число, а метод ожидает «четыре цифры или более в год» (цитируется из документации DateTimeFormatter.ISO_LOCAL_DATE). Во-вторых, вы не хотите измерять прошедшее время в минутах на основе даты без времени суток. В-третьих, вы не можете разобрать строку даты без времени дня в LocalDateTime (есть хитрости, но это не работает просто так).

Ссылки

...