[英]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.kt在PostActivity上传帖子 > firebase保存帖子的数据(帖子由 postId、writerId、message、writeTime、bgUri for image、commentCount 组成) > MainActivity从 firebase 获取数据并通过MyAdapter.kt在RecycleView上显示帖子
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(). post
的writeTime
字段是 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首先在数据库中节省时间
val h = picker.hour
val m = picker.minute
val hour = TimeUnit.HOURS.toMillis(h.toLong())
val minute = TimeUnit.MINUTES.toMillis(m.toLong())
val totalTime = hour + minute
Now retrieving the time from database现在从数据库中检索时间
val timeMilliseconds = totalTime.toLong()
val startTime = formatToDigitalClock(timeMilliseconds)
//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.