簡體   English   中英

如何更改日期時間的格式?

[英]How can I change the format of DateTime?

我正在嘗試制作一種字符串格式,當上傳用戶帖子時,它將上傳時間表示為“〜分鍾前”或“〜小時前”等等。

我的應用程序的工作方式如下

PostActivity上傳帖子 > firebase保存帖子的數據(帖子由 postId、writerId、message、writeTime、bgUri for image、commentCount 組成) > MainActivity從 firebase 獲取數據並通過MyAdapter.ktRecycleView上顯示帖子

下面是PostActivity.kt

class PostActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_post)

      supportActionBar?.title = "New Post"
      val layoutManager = LinearLayoutManager(this@PostActivity)
      layoutManager.orientation = LinearLayoutManager.HORIZONTAL

    
      recyclerView2.layoutManager=layoutManager
      recyclerView2.adapter = MyAdapter()

      postButton.setOnClickListener {

         val newRef = FirebaseDatabase.getInstance().getReference("Posts").push()
         
         post.writeTime= DateTime().toString()

         newRef.setValue(post)
         finish()
     }
 }

postwriteTime字段是 DateTime().toString()。

對於字符串格式,我在下面的MyAdapter.kt中創建了 function getdiffTimeText()

class MyAdapter(private val posts : MutableList<Post>) :  RecyclerView.Adapter<MyAdapter.MyViewHolder>() { //line 20
   
   override fun onBindViewHolder(holder: MyAdapter.MyViewHolder, position: Int) {
       val post = posts[position]

       holder.timeTextView.text = getDiffTimeText(post.writeTime) //line 32 
   }

   public class MyViewHolder(itemView : View) : 
       val timeTextView = itemView?.findViewById<TextView>(R.id.timeTextView) //line 51           
   }
}
fun getDiffTimeText(targetTime: String): String {

   val curDateTime = DateTime()
   val targetDateTime = DateTime(targetTime)

   val diffDay = Days.daysBetween(curDateTime, targetDateTime).days
   val diffHours = Hours.hoursBetween(targetDateTime, curDateTime).hours
   val diffMinutes = Minutes.minutesBetween(targetDateTime, curDateTime).minutes
   if (diffDay == 0) {
       if (diffDay == 0 && diffMinutes == 0) {
           return "just before"
       }
       return if (diffHours > 0) {
           "" + diffHours + "hours ago"
       } else "" + diffMinutes + "minutes ago"

   } else {
       val format = SimpleDateFormat("yyyy.MM.dd")
       return format.format(Date(targetTime))
   }
}

下面是 MainActivity

class MainActivity : AppCompatActivity() {

   val posts: MutableList<Post> = mutableListOf()

   private lateinit var dbref: DatabaseReference

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      getUserData()
   }

   private fun getUserData() {
      dbref = FirebaseDatabase.getInstance().getReference("/Posts")
      dbref.addValueEventListener(object : ValueEventListener {
         override fun onDataChange(snapshot: DataSnapshot) {
            if (snapshot.exists()) {
                for (userSnapshot in snapshot.children) {
                    val post = userSnapshot.getValue(Post::class.java)
                    posts.add(post!!)
                }
                recyclerView_main.adapter = MyAdapter(posts)
             }
         }

         override fun onCancelled(error: DatabaseError) {
    Toast.makeText(this@MainActivity,"failed",Toast.LENGTH_SHORT).show()
         }
     })
  }
}

下面是 Post.kt 用戶帖子的 class。

class Post {
var postId = ""
var writerId = ""
var message = ""

var writeTime = ""

var bgUri = ""
var commentCount = ""
}

當我運行代碼時,應用程序崩潰並出現以下錯誤。

java.lang.IllegalArgumentException: Invalid format: "1661861458" is malformed at "8"
   
    at org.joda.time.DateTime.<init>(DateTime.java:257)
    at <<package name>>.MyAdapterKt.getDiffTimeText(MyAdapter.kt:51)
    at <<package name>>.MyAdapter.onBindViewHolder(MyAdapter.kt:32)
    at <<package name>>.MyAdapter.onBindViewHolder(MyAdapter.kt:20)
   

為了測試函數getDiffTimeText()我在不同的活動中嘗試了下面的代碼。

val testTime = DateTime().toString()

val testText = findViewById<TextView>(R.id.testing)
val testText2 = findViewById<TextView>(R.id.testing2)

testText.text = testTime
testText2.text = getDiffTimeText(testTime)

testTime是 String 類型,就像 Post.kt 中 writeTime 字段的類型是 String 一樣。

結果,textview testText顯示2022-08-31T05:37:55.778Z是當前時間,而testText2顯示just ago 所以似乎 function getDiffTimeText以這種方式工作。 但它在 MyAdapter.kt 第 32 行的holder.timeTextView.text = getDiffTimeText(post.writeTime)MyAdapter.kt ,並且應用程序崩潰。 我應該如何解決這個問題?

*為了清楚起見,編輯了我的問題,不相關的代碼被排除在外。

似乎您在第 32 行holder.timeTextView.text = getDiffTimeText(post.writeTime)中傳遞的時間戳是以秒而不是毫秒計算的。

您可以嘗試將遠程時間更改為毫秒或只是這樣做:

val timeInMillis = post.writeTime.toLong() * 1000L // maybe toLongOrNull() for safe usage.
holder.timeTextView.text = getDiffTimeText(timeInMillis.toString())

我使用這種方法來解決我的問題:雖然在我的情況下我只是計算時間而不是日期。 但你可以有一些想法。

所以我試圖以毫秒為單位存儲時間,然后將其取回以顯示所需的格式:

以下是我遵循的步驟:

首先在數據庫中節省時間

  1. 從時間選擇器獲取時間:
val h = picker.hour
val m = picker.minute
  1. 將總時間轉換為毫秒
val hour = TimeUnit.HOURS.toMillis(h.toLong())
val minute = TimeUnit.MINUTES.toMillis(m.toLong())
val totalTime = hour + minute
  1. 將時間保存為字符串。 (在我的例子中是 Room DB,你可以在 Firebase 上做)

現在從數據庫中檢索時間

  1. 最初將輸入的時間從 String 轉換回 Long
  val timeMilliseconds = totalTime.toLong()
  1. 在 function 的幫助下將毫秒轉換為小時、分鍾和秒
 val startTime = formatToDigitalClock(timeMilliseconds)
  1. function
//Converting received long time to proper digital format
    private fun formatToDigitalClock(milliseconds: Long): String {
        val hours = TimeUnit.MILLISECONDS.toHours(milliseconds).toInt() % 24
        val minutes = TimeUnit.MILLISECONDS.toMinutes(milliseconds).toInt() % 60
        val seconds = TimeUnit.MILLISECONDS.toSeconds(milliseconds).toInt() % 60

        return when {
            hours > 0 -> String.format("%d:%02d:%02d", hours, minutes, seconds)
            minutes > 0 -> String.format("%02d:%02d", minutes, seconds)
            seconds > 0 -> String.format("00:%02d", seconds)

            else -> {
                "00:00"
            }
        }
    }

您可以以某種方式進一步更改字符串格式,以便您可以顯示您的時間(“2 小時前”)

如果post.writeTime.toLong()導致java.lang.NumberFormatException: For input string: "2022-08-31T04:20:45.265Z" ,我必須得出結論post.writeTime的類型是 ISO 中的String標准。

有一種簡單的方法可以解析java.time中的那些 ISO 標准,在這種情況下你可以這樣做

OffsetDateTime.parse(post.writeTime)

並使用它來計算到現在為止的差異/時間(在代碼中: OffsetDateTime.now(ZoneOffset.UTC) )。 您將需要一個ZoneOffset因為post.writeTime返回的String也有一個(最后的Z是 UTC 和 +00:00 小時的偏移量)。

經過的時間可以通過java.time.Duration來計算:

val duration = Duration.between(
                   OffsetDateTime.parse(post.writeTime),
                   OffsetDateTime.now(ZoneOffset.UTC)
               )

我認為, Duration時間以小時、分鍾、秒、毫秒甚至納秒為單位表示經過的時間。 但是,這里只有小時、分鍾和秒才重要(如果我錯了,請糾正我)。

現在 Kotlin 魔法開始發揮作用:我們可以為Duration編寫一個擴展 function ,它只是自上而下檢查值(小時優先,如果為零,使用分鍾,如果為零,使用秒,如果為零,請寫一些語句):

fun Duration.timeAgo(): String {
    return when {
        this.toHours() > 0 -> "${this.toHours()} hours ago"
        this.toMinutes() > 0 -> "${this.toMinutes()} minutes ago"
        this.toSeconds() > 0 -> "${this.toSeconds()} seconds ago"
        else -> "a moment ago"
    }
}

使用您在另一個答案下方的評論中的時間String和上面提到的代碼(在此答案中)的main示例:

fun main() {
    val duration = Duration.between(
        OffsetDateTime.parse("2022-08-31T04:20:45.265Z"),
        OffsetDateTime.now(ZoneOffset.UTC)
    )

    println(duration.timeAgo())
}

結果(注意,這取決於代碼的運行時間):

3 hours ago

Duration不同值的一些示例:

fun main() {
    val durOne = Duration.ofHours(2).plusMinutes(13).plusSeconds(53)
    val durTwo = Duration.ofMinutes(13).plusSeconds(53)
    val durThree = Duration.ofSeconds(53).plusMillis(20)
    val durFour = Duration.ofMillis(20)

    println("${durOne.timeAgo()}")
    println("${durTwo.timeAgo()}")
    println("${durThree.timeAgo()}")
    println("${durFour.timeAgo()}")
}

Output:

2 hours ago
13 minutes ago
53 seconds ago
a moment ago

我的數據庫中有我之前存儲的數據,我錯過了這些數據在寫入時間方面具有不同的結構。 這導致加載數據時崩潰。 刪除這些后,它運行良好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM