Home > Mobile >  How can I change the format of DateTime?
How can I change the format of DateTime?

Time:08-31

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

Below is the 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().

For the string format, I made a function getdiffTimeText() at MyAdapter.kt which is below.

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

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.

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.

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.

As the result, textview testText shows 2022-08-31T05:37:55.778Z which is the current time, and testText2 shows just ago. So it seems the function getDiffTimeText works in this way. But It doesn't work in holder.timeTextView.text = getDiffTimeText(post.writeTime) which is MyAdapter.kt line 32, and the app crashes. How should I solve this?

*edited my question for clearence, codes that are less relevant are excluded.

CodePudding user response:

Seem the timestamp you passed in line 32 holder.timeTextView.text = getDiffTimeText(post.writeTime) is counting with second instead of millis.

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

CodePudding user response:

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)

Now retrieving the time from database

  1. Initially converted the entered time back to Long from String
  val timeMilliseconds = totalTime.toLong()
  1. Converting the milliseconds to hours, minutes and seconds with help of function
 val startTime = formatToDigitalClock(timeMilliseconds)
  1. The 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:d:d", hours, minutes, seconds)
            minutes > 0 -> String.format("d:d", minutes, seconds)
            seconds > 0 -> String.format("00:d", 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")

  • Related