Home > Blockchain >  How would I make a relative date (like 1 second ago, 2 weeks ago)
How would I make a relative date (like 1 second ago, 2 weeks ago)

Time:08-05

I tried

Text(Date.now, format:
                     .relative(presentation: .named))

and also tried

Text(Date.now, style: .relative)

But the first one just says "now" even after 24 hours

and the second one is literally just a timer so instead of saying after one minute "1 minute ago" it says "1 minute, 20 seconds" for example. There aren't a lot of resources out there for this particular thing, so help will be appreciated

CodePudding user response:

Relative format presents date relatively to "now", it does not track time, we have to provide date explicitly, like

Text(Date().addingTimeInterval(-60), format:
         .relative(presentation: .named))

rendered as

demo

CodePudding user response:

The reason that your first one would stay saying "now", while the second one will update once a second is because:

  • The first one simply converts the input data to a string when the Text view is first created.

  • The second one is a initializer that is specialized for Date. It actually creates a publisher behind the scene, that will update the underlying text once a second. However, as you might have found out already, only a few DateStyle were supported.


One solution is to create your own Date wrapper class that conforms to ObservableObject:

class PublishedDate: ObservableObject {
    let date = Date.now

    /// Manually creating a publisher that will emits once a second
    var objectWillChange = Timer.publish(every: 1, on: .main, in:.common).autoconnect()
}

Now we can store our PublishedDate in the view as a @StateObject, and it will update relevant sub-views every time objectWillChange fires:

struct ContentView: View {
    @StateObject var date: PublishedDate = .init()
    var body: some View {
        VStack {
            Text(date.date.formatted(.relative(presentation: .named)))
        }
    }
}
  • Related