简体   繁体   English

如何更改日期时间的格式?

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

I'm trying to make a string format that, when a user post is uploaded, it expresses the upload time as "~ minutes ago" or "~ hours ago" and so on.我正在尝试制作一种字符串格式,当上传用户帖子时,它将上传时间表示为“〜分钟前”或“〜小时前”等等。

My application works in the way like below我的应用程序的工作方式如下

upload post in PostActivity > firebase saves the data of the post (the post is consist of postId, writerId, message, writeTime, bgUri for image, commentCount) > MainActivity gets data from firebase and shows the post on RecycleView by MyAdapter.ktPostActivity上传帖子 > firebase保存帖子的数据(帖子由 postId、writerId、message、writeTime、bgUri for image、commentCount 组成) > MainActivity从 firebase 获取数据并通过MyAdapter.ktRecycleView上显示帖子

Below is the PostActivity.kt下面是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()
     }
 }

The writeTime field of post is DateTime().toString(). postwriteTime字段是 DateTime().toString()。

For the string format, I made a function getdiffTimeText() at MyAdapter.kt which is below.对于字符串格式,我在下面的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))
   }
}

Below is the MainActivity下面是 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()
         }
     })
  }
}

Below is Post.kt the class of user's post.下面是 Post.kt 用户帖子的 class。

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

var writeTime = ""

var bgUri = ""
var commentCount = ""
}

When I run the code, app crashes with the error below.当我运行代码时,应用程序崩溃并出现以下错误。

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)
   

To test the fuction getDiffTimeText() I tried the code below in different activity.为了测试函数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)

The testTime is String type just like the Post.kt where the type of writeTime field is String. testTime是 String 类型,就像 Post.kt 中 writeTime 字段的类型是 String 一样。

As the result, textview testText shows 2022-08-31T05:37:55.778Z which is the current time, and testText2 shows just ago .结果,textview testText显示2022-08-31T05:37:55.778Z是当前时间,而testText2显示just ago So it seems the function getDiffTimeText works in this way.所以似乎 function getDiffTimeText以这种方式工作。 But It doesn't work in holder.timeTextView.text = getDiffTimeText(post.writeTime) which is MyAdapter.kt line 32, and the app crashes.但它在 MyAdapter.kt 第 32 行的holder.timeTextView.text = getDiffTimeText(post.writeTime)MyAdapter.kt ,并且应用程序崩溃。 How should I solve this?我应该如何解决这个问题?

*edited my question for clearence, codes that are less relevant are excluded. *为了清楚起见,编辑了我的问题,不相关的代码被排除在外。

Seem the timestamp you passed in line 32 holder.timeTextView.text = getDiffTimeText(post.writeTime) is counting with second instead of millis.似乎您在第 32 行holder.timeTextView.text = getDiffTimeText(post.writeTime)中传递的时间戳是以秒而不是毫秒计算的。

You can try to changed your remote time to millis or just do like that:您可以尝试将远程时间更改为毫秒或只是这样做:

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

I used this approach to fix my issue: Though in my case I was just calculating the time and not date.我使用这种方法来解决我的问题:虽然在我的情况下我只是计算时间而不是日期。 But you can have some idea.但你可以有一些想法。

So I was trying to store the time in milliseconds and then retrieving it back to show in a desired format:所以我试图以毫秒为单位存储时间,然后将其取回以显示所需的格式:

Here are the steps I followed:以下是我遵循的步骤:

First saving the time in database首先在数据库中节省时间

  1. Getting the time from Time Picker:从时间选择器获取时间:
val h = picker.hour
val m = picker.minute
  1. Converting the total time to milliseconds将总时间转换为毫秒
val hour = TimeUnit.HOURS.toMillis(h.toLong())
val minute = TimeUnit.MINUTES.toMillis(m.toLong())
val totalTime = hour + minute
  1. Saving the time as a string.将时间保存为字符串。 (in my case it was Room DB, you can do on Firebase) (在我的例子中是 Room DB,你可以在 Firebase 上做)

Now retrieving the time from database现在从数据库中检索时间

  1. Initially converted the entered time back to Long from String最初将输入的时间从 String 转换回 Long
  val timeMilliseconds = totalTime.toLong()
  1. Converting the milliseconds to hours, minutes and seconds with help of function在 function 的帮助下将毫秒转换为小时、分钟和秒
 val startTime = formatToDigitalClock(timeMilliseconds)
  1. The function 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"
            }
        }
    }

You can further change the String format in a way so that you can show your time like ("2 hours ago")您可以以某种方式进一步更改字符串格式,以便您可以显示您的时间(“2 小时前”)

If post.writeTime.toLong() causes a java.lang.NumberFormatException: For input string: "2022-08-31T04:20:45.265Z" , I'll have to conclude that the type of post.writeTime is String in ISO standard.如果post.writeTime.toLong()导致java.lang.NumberFormatException: For input string: "2022-08-31T04:20:45.265Z" ,我必须得出结论post.writeTime的类型是 ISO 中的String标准。

There's a simple way to parse those ISO standards in java.time , in this case you can do有一种简单的方法可以解析java.time中的那些 ISO 标准,在这种情况下你可以这样做

OffsetDateTime.parse(post.writeTime)

and use that to calculate the difference / time elapsed until now (in code: OffsetDateTime.now(ZoneOffset.UTC) ).并使用它来计算到现在为止的差异/时间(在代码中: OffsetDateTime.now(ZoneOffset.UTC) )。 You will need a ZoneOffset because the String returned by post.writeTime also has one (the Z at the end is UTC resp. an offset of +00:00 hours).您将需要一个ZoneOffset因为post.writeTime返回的String也有一个(最后的Z是 UTC 和 +00:00 小时的偏移量)。

The elapsed time can be calculated by means of a java.time.Duration :经过的时间可以通过java.time.Duration来计算:

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

A Duration represents elapsed time in hours, minutes, seconds, millis and even nanos, I think.我认为, Duration时间以小时、分钟、秒、毫秒甚至纳秒为单位表示经过的时间。 However, only hours, minutes and seconds should matter here (correct me if I'm wrong).但是,这里只有小时、分钟和秒才重要(如果我错了,请纠正我)。

Now the Kotlin magic comes into play: We can write an extension function for Duration , one that simply checks the values top-down (hours first, if zero, use minutes, if zero, use seconds, if zero write some statement):现在 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"
    }
}

Example in a main using the time String from your comment below another answer and the code mentioned above (in this answer):使用您在另一个答案下方的评论中的时间String和上面提到的代码(在此答案中)的main示例:

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

    println(duration.timeAgo())
}

Result (attention, it depends on the runtime of the code):结果(注意,这取决于代码的运行时间):

3 hours ago

Some examples with Duration s of differen values: 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: Output:

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

there were data on my database which I stored before, and I missed that those data had different structure about writetime.我的数据库中有我之前存储的数据,我错过了这些数据在写入时间方面具有不同的结构。 So that caused the crash on loading data.这导致加载数据时崩溃。 After removing those, it worked well.删除这些后,它运行良好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何更改汇编语言上的字符串显示? - How can I able to change the String display on Assembly Language? 我究竟如何设置受保护的分支正则表达式格式以限制可以推送到 repo 的内容? - How exactly do I set the protected branches regex format to limit what can be pushed to the repo? 我想在谷歌大查询中将格式为“2019-06-24T22:17:05.000Z”的日期时间列转换为 PST - I want to convert datetime column with the format of "2019-06-24T22:17:05.000Z" to PST in google big query 如何更改 Google bigtable (nodejs) 中的 grpc.max_receive_message_length 配置? - How can I change the grpc.max_receive_message_length configuration in Google bigtable (nodejs)? 如何根据项目中的文件路径位置动态更改目标数据集? - How can I change the target dataset dynamically based on the file path location in the project? 如何保护或更改托管在 Google Cloud Platform 上的 wordpress 网站的 phpmyadmin? - How can I secure or change phpmyadmin for my wordpress site that is hosted on Google Cloud Platform? 如何使用 useEffect 将 firebase 实时数据库中的更改显示到我的页面? - How can I show the change in firebase realtime database to my page with useEffect? 如何更改 AWS Amplify 中的环境 - How do I change environments in AWS Amplify 如何在创建 AWS Cognito 用户池时更改 phone_number 格式? - How to change phone_number format upon creation of a AWS Cognito User Pool? 我无法在 firestore 数据库集合中将列 Kind 更改为 Type - I can't change the column Kind to Type on the firestore database collection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM