Calculate time between Current Time and Old Time Swift - swift

I am working on Date and Time where I keep a log of logged in and logged out. For e.g. Logged in time is 12:45 and Logged Out time is 1:45 so need to check the total hour's user was online. I have both time and below is the code where I am trying to check max hour's by adding but I am not getting the output I need.
//Current time
let formatter = DateFormatter()
formatter.timeStyle = .medium
formatter.dateStyle = .none
outTimeString = formatter.string(from: currentDateTime) as NSString
//LoggedIn Time
inTimeString = "12:49:50"
let inFormatter = DateFormatter()
inFormatter.dateFormat = "HH:mm:ss"
let outFormatter = DateFormatter()
outFormatter.dateFormat = "hh:mm"
let inTime = inTimeString
let date = inFormatter.date(from: inTime)!
let inStr = outFormatter.string(from: date)
print(inStr)->12:49:50
let outTime = outTimeString
let outDate = inFormatter.date(from: outTime as String)!
let outStr = outFormatter.string(from: outDate)
print(outStr)->16:10:15
//Adding 4 hour to logged in timw
let calendar = NSCalendar.current
let finaldate = date.addingTimeInterval(-4 * 60.0 * 60.0)
print(finaldate)->2000-01-01 03:19:50 +0000
Problem is I am getting the output wrong when 4 hours are added to the logged in time.
I need the total time logged in or add 4 hours to the original logged in time. Any one will do.
Help is much appreciated.

Calculating total time logged in.
var totalTimeLoggedIn: TimeInterval = 3600 // 1 hour
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy HH:mm:ss"
guard
let loginTimeDate = dateFormatter.date(from: "26-04-2018 12:00:00"),
let logoutTimeDate = dateFormatter.date(from: "26-04-2018 13:00:00")
else {
return
}
let timeLoggedIn = logoutTimeDate.timeIntervalSince(loginTimeDate)
totalTimeLoggedIn += timeLoggedIn
print("totalTimeLoggedIn: \(totalTimeLoggedIn.stringValue())") // totalTimeLoggedIn: 02:00:00
Extension used for printing total login time in hours:minutes:seconds.
extension TimeInterval {
/// Returns the time interval into a string value in hours:minutes:seconds (e.g. 09:15:34)
func stringValue(removeHoursIfEmpty:Bool = true) -> String {
if(self.isNaN){
return "00:00"
}
var value = self
if value < 0 {
value = 0
}
let hours:Int = Int(value / 3600)
let minutes:Int = Int((value.truncatingRemainder(dividingBy: 3600)) / 60)
let seconds:Int = Int(value.truncatingRemainder(dividingBy: 60))
if (hours > 0 || removeHoursIfEmpty == false){
return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
} else {
return String(format: "%02d:%02d", minutes, seconds)
}
}
}

Try the below code, hopefully it will help you.
func findIntervalBtwToDate(startingDate: String, endingDate : String) -> TimeInterval {
var interval = 0.0
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(name: "UTC")! as TimeZone
guard let endDate = dateFormatter.date(from: endingDate), let startDate = dateFormatter.date(from: startingDate) else { return interval }
interval = endDate.timeIntervalSince(startDate)
return interval
}

Related

UTC time conversion: How do I convert an integer (UTC) into a 'datetime' time stamp? [duplicate]

My current code:
if let var timeResult = (jsonResult["dt"] as? Double) {
timeResult = NSDate().timeIntervalSince1970
println(timeResult)
println(NSDate())
}
The results:
println(timeResult) = 1415639000.67457
println(NSDate()) = 2014-11-10 17:03:20 +0000 was just to test to see what NSDate was providing.
I want the first to look like the last. The value for dt = 1415637900.
Also, how can I adjust to time zone? Running on iOS.
You can get a date with that value by using the NSDate(withTimeIntervalSince1970:) initializer:
let date = NSDate(timeIntervalSince1970: 1415637900)
To get the date to show as the current time zone I used the following.
if let timeResult = (jsonResult["dt"] as? Double) {
let date = NSDate(timeIntervalSince1970: timeResult)
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.MediumStyle //Set time style
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle //Set date style
dateFormatter.timeZone = NSTimeZone()
let localDate = dateFormatter.stringFromDate(date)
}
Swift 3.0 Version
if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = self.timeZone
let localDate = dateFormatter.string(from: date)
}
Swift 5
if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = .current
let localDate = dateFormatter.string(from: date)
}
It's simple to convert the Unix timestamp into the desired format. Lets suppose _ts is the Unix timestamp in long
let date = NSDate(timeIntervalSince1970: _ts)
let dayTimePeriodFormatter = NSDateFormatter()
dayTimePeriodFormatter.dateFormat = "MMM dd YYYY hh:mm a"
let dateString = dayTimePeriodFormatter.stringFromDate(date)
print( " _ts value is \(_ts)")
print( " _ts value is \(dateString)")
For managing dates in Swift 3 I ended up with this helper function:
extension Double {
func getDateStringFromUTC() -> String {
let date = Date(timeIntervalSince1970: self)
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.dateStyle = .medium
return dateFormatter.string(from: date)
}
}
This way it easy to use whenever you need it - in my case it was converting a string:
("1481721300" as! Double).getDateStringFromUTC() // "Dec 14, 2016"
Reference the DateFormatter docs for more details on formatting (Note that some of the examples are out of date)
I found this article to be very helpful as well
Here is a working Swift 3 solution from one of my apps.
/**
*
* Convert unix time to human readable time. Return empty string if unixtime
* argument is 0. Note that EMPTY_STRING = ""
*
* #param unixdate the time in unix format, e.g. 1482505225
* #param timezone the user's time zone, e.g. EST, PST
* #return the date and time converted into human readable String format
*
**/
private func getDate(unixdate: Int, timezone: String) -> String {
if unixdate == 0 {return EMPTY_STRING}
let date = NSDate(timeIntervalSince1970: TimeInterval(unixdate))
let dayTimePeriodFormatter = DateFormatter()
dayTimePeriodFormatter.dateFormat = "MMM dd YYYY hh:mm a"
dayTimePeriodFormatter.timeZone = NSTimeZone(name: timezone) as TimeZone!
let dateString = dayTimePeriodFormatter.string(from: date as Date)
return "Updated: \(dateString)"
}
func timeStringFromUnixTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
// Returns date formatted as 12 hour time.
dateFormatter.dateFormat = "hh:mm a"
return dateFormatter.stringFromDate(date)
}
func dayStringFromTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
dateFormatter.locale = NSLocale(localeIdentifier: NSLocale.currentLocale().localeIdentifier)
dateFormatter.dateFormat = "EEEE"
return dateFormatter.stringFromDate(date)
}
In Swift 5
Using this implementation you just have to give epoch time as a parameter and you will the output as (1 second ago, 2 minutes ago, and so on).
func setTimestamp(epochTime: String) -> String {
let currentDate = Date()
let epochDate = Date(timeIntervalSince1970: TimeInterval(epochTime) as! TimeInterval)
let calendar = Calendar.current
let currentDay = calendar.component(.day, from: currentDate)
let currentHour = calendar.component(.hour, from: currentDate)
let currentMinutes = calendar.component(.minute, from: currentDate)
let currentSeconds = calendar.component(.second, from: currentDate)
let epochDay = calendar.component(.day, from: epochDate)
let epochMonth = calendar.component(.month, from: epochDate)
let epochYear = calendar.component(.year, from: epochDate)
let epochHour = calendar.component(.hour, from: epochDate)
let epochMinutes = calendar.component(.minute, from: epochDate)
let epochSeconds = calendar.component(.second, from: epochDate)
if (currentDay - epochDay < 30) {
if (currentDay == epochDay) {
if (currentHour - epochHour == 0) {
if (currentMinutes - epochMinutes == 0) {
if (currentSeconds - epochSeconds <= 1) {
return String(currentSeconds - epochSeconds) + " second ago"
} else {
return String(currentSeconds - epochSeconds) + " seconds ago"
}
} else if (currentMinutes - epochMinutes <= 1) {
return String(currentMinutes - epochMinutes) + " minute ago"
} else {
return String(currentMinutes - epochMinutes) + " minutes ago"
}
} else if (currentHour - epochHour <= 1) {
return String(currentHour - epochHour) + " hour ago"
} else {
return String(currentHour - epochHour) + " hours ago"
}
} else if (currentDay - epochDay <= 1) {
return String(currentDay - epochDay) + " day ago"
} else {
return String(currentDay - epochDay) + " days ago"
}
} else {
return String(epochDay) + " " + getMonthNameFromInt(month: epochMonth) + " " + String(epochYear)
}
}
func getMonthNameFromInt(month: Int) -> String {
switch month {
case 1:
return "Jan"
case 2:
return "Feb"
case 3:
return "Mar"
case 4:
return "Apr"
case 5:
return "May"
case 6:
return "Jun"
case 7:
return "Jul"
case 8:
return "Aug"
case 9:
return "Sept"
case 10:
return "Oct"
case 11:
return "Nov"
case 12:
return "Dec"
default:
return ""
}
}
How to call?
setTimestamp(epochTime: time) and you'll get the desired output as a string.
Convert timestamp into Date object.
If timestamp object is invalid then return current date.
class func toDate(_ timestamp: Any?) -> Date? {
if let any = timestamp {
if let str = any as? NSString {
return Date(timeIntervalSince1970: str.doubleValue)
} else if let str = any as? NSNumber {
return Date(timeIntervalSince1970: str.doubleValue)
}
}
return nil
}
Swift:
extension Double {
func getDateStringFromUnixTime(dateStyle: DateFormatter.Style, timeStyle: DateFormatter.Style) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = dateStyle
dateFormatter.timeStyle = timeStyle
return dateFormatter.string(from: Date(timeIntervalSince1970: self))
}
}
Anyway #Nate Cook's answer is accepted but I would like to improve it with better date format.
with Swift 2.2, I can get desired formatted date
//TimeStamp
let timeInterval = 1415639000.67457
print("time interval is \(timeInterval)")
//Convert to Date
let date = NSDate(timeIntervalSince1970: timeInterval)
//Date formatting
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd, MMMM yyyy HH:mm:a"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let dateString = dateFormatter.stringFromDate(date)
print("formatted date is = \(dateString)")
the result is
time interval is 1415639000.67457
formatted date is = 10, November 2014 17:03:PM
If you are maximizing the Codable protocol for parsing your JSON data. You could simply make the data type of dt as Date and do:
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
For me: Converting timestamps coming from API to a valid date :
`let date = NSDate.init(fromUnixTimestampNumber: timesTamp /* i.e 1547398524000 */) as Date?`
By using this code you will be able to convert timeStamp to Time and Date
let timeStamp = Date().timeIntervalSince1970
let date = NSDate(timeIntervalSince1970: timeStamp)
let dayTimePeriodFormatter = DateFormatter()
dayTimePeriodFormatter.dateFormat = "dd MMMM,YYYY.hh:mm a"
let dateTimeString = dayTimePeriodFormatter.string(from: date as Date)
let dateTime = dateTimeString.split(separator: ".")
print( "Date = \(dateTime[0])")
print( "Time = \(dateTime[1])")
Output:
Date = 19 January,2022
Time = 10:46 AM

How to convert date "MM-dd-yyyy hh:mm:ss a" into text format?

I am trying to create a function which will convert date into text format like "Just now, 2mins, 1hour, 1day, oct 10". Here is my sample code where I am getting an error at:
let components = cal.components([.Day,.Hour,.Minute], fromDate: date, toDate: NSDate(), options:[])
Here is my full code:
func getTextToDisplayFormattingDate(date: NSDate) -> String {
var textToDisplay = ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy hh:mm:ss a"
dateFormatter.timeZone = TimeZone(identifier: "UTC")
let cal = NSCalendar.current
let components = cal.components([.Day,.Hour,.Minute], fromDate: date, toDate: NSDate(), options:[])
switch components.day {
case 0:
if components.hour == 0 {
if components.minute <= 0 {
textToDisplay = "just now "
} else {
textToDisplay = "\(components.minute) min"
}
} else {
textToDisplay = "\(components.hours) hrs"
}
case 1...6:
textToDisplay = "\(components.day) d"
default:
dateFormatter.dateFormat = "MMM dd"
textToDisplay = dateFormatter.string(from: date as Date)
}
return textToDisplay
}
Use like this :
Changes in my code :
In place of NSDate, I used Date.
In place of NSCalendar I used Calendar
components(_:from:to:options:) has been renamed to dateComponents(_:from:to:)
components values like day, minute, hour are optional. Thats why i added check before switch.
func getTextToDisplayFormattingDate(date: Date) -> String {
var textToDisplay = ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy hh:mm:ss a"
dateFormatter.timeZone = TimeZone(identifier: "UTC")
let cal = Calendar.current
let components = cal.dateComponents([.day, .hour , .minute], from: date, to: Date())
if let day = components.day, let minute = components.minute, let hour = components.hour {
switch day {
case 0:
if hour == 0 {
if minute <= 0 {
textToDisplay = "just now "
} else {
textToDisplay = "\(minute) min"
}
} else {
textToDisplay = "\(hour) hrs"
}
case 1...6:
textToDisplay = "\(day) d"
default:
dateFormatter.dateFormat = "MMM dd"
textToDisplay = dateFormatter.string(from: date)
}
}
return textToDisplay
}
Actually, it's hard to calculate the days, hours, minutes between 2 dates by NSCalendar.components, your procedure will cause an unexpected result. Usually, we calculate it by the TimeInterval between them. Try this in swift 3.2 or swift 4.0:
func getTextToDisplayFormattingDate(date: Date) -> String {
var textToDisplay = ""
let now = Date()
let timeInterval = now.timeIntervalSince(date)
if timeInterval < 60 {
textToDisplay = "just now "
}
else if timeInterval < 60 * 60 {
textToDisplay = "\(Int(timeInterval / 60)) min"
}
else if timeInterval < 60 * 60 * 24 {
textToDisplay = "\(Int(timeInterval / 60 / 60)) hrs"
}
else {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(identifier: "UTC")
if timeInterval < 60 * 60 * 24 * 6 { //less than 6 days
// For getting days
// textToDisplay = "\(Int(timeInterval / 60 / 60 / 24)) d"
// For getting weekday name
dateFormatter.dateFormat = "EEEE"
textToDisplay = dateFormatter.string(from: date) //weekday name
}
else{
dateFormatter.dateFormat = "MMM dd"
textToDisplay = dateFormatter.string(from: date as Date)
}
}
return textToDisplay
}
And remember use constants to replace expresses like 60 * 60 * 24 to improve performance.

Unix time stamp conversion issue in swift 3

I am trying to convert the timestamp from server and it is converting also but only month is coming wrong.Like timestamp is 1492747393892 and it convert into 21/03/17 - 12:03PM but it should be 21/04/17 - 12:03PM.
Here is my code
var arriveTimestamp: Int
if let timeStampToDate = arriveTimestamp {
let timeSt = Date(jsonTimeDate:"/Date(\(timeStampToDate))/")
let time = Date().dateTime(date: timeSt!)
valueLbl.text = time
}
init?(jsonTimeDate: String) {
// "/Date(1487058855745)/"
let prefix = "/Date("
let suffix = ")/"
let scanner = Scanner(string: jsonTimeDate)
// Check prefix:
guard scanner.scanString(prefix, into: nil) else { return nil }
// Read milliseconds part:
var milliseconds : Int64 = 0
guard scanner.scanInt64(&milliseconds) else { return nil }
// Milliseconds to seconds:
var timeStamp = TimeInterval(milliseconds)/1000.0
// Read optional timezone part:
var timeZoneOffset : Int = 0
if scanner.scanInt(&timeZoneOffset) {
let hours = timeZoneOffset / 100
let minutes = timeZoneOffset % 100
// Adjust timestamp according to timezone:
timeStamp += TimeInterval(3600 * hours + 60 * minutes)
}
// Check suffix:
guard scanner.scanString(suffix, into: nil) else { return nil }
// Success! Create NSDate and return.
self.init(timeIntervalSince1970: timeStamp)
}
func dateTime(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/mm/yy - hh:mm a"
return dateFormatter.string(from: date as Date)
}
The main error in your code is the wrong date format for the month,
which should be "MM", not "mm" (which is for the minutes).
Apart from that, your approach is far too complicated. All you have to
do is to divide the timestamp (which is in milliseconds) by 1000
and call Date(timeIntervalSince1970:):
let arriveTimestamp = 1492747393892
let date = Date(timeIntervalSince1970: TimeInterval(arriveTimestamp)/1000)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yy - hh:mm a"
let text = dateFormatter.string(from: date)
print(text) // 21/04/17 - 06:03 AM

How to get timezone offset as ±hh:mm?

I can get the offset seconds from GMT with this: TimeZone.current.secondsFromGMT().
However, how do I get the format as ±hh:mm?
Some integer arithmetic to obtain the offset in hours and
minutes:
let seconds = TimeZone.current.secondsFromGMT()
let hours = seconds/3600
let minutes = abs(seconds/60) % 60
Formatted printing:
let tz = String(format: "%+.2d:%.2d", hours, minutes)
print(tz) // "+01:00"
%.2d prints an integer with (at least) two decimal digits (and leading
zero if necessary). %+.2d is the same but with a leading + sign for
non-negative numbers.
Here is extension for getting timezone offset Difference and as ±hh:mm (Swift 4 | Swift 5 Code)
extension TimeZone {
func offsetFromUTC() -> String
{
let localTimeZoneFormatter = DateFormatter()
localTimeZoneFormatter.timeZone = self
localTimeZoneFormatter.dateFormat = "Z"
return localTimeZoneFormatter.string(from: Date())
}
func offsetInHours() -> String
{
let hours = secondsFromGMT()/3600
let minutes = abs(secondsFromGMT()/60) % 60
let tz_hr = String(format: "%+.2d:%.2d", hours, minutes) // "+hh:mm"
return tz_hr
}
}
Use like this
print(TimeZone.current.offsetFromUTC()) // output is +0530
print(TimeZone.current.offsetInHours()) // output is "+05:30"
If you can use Date()
func getCurrentTimezone() -> String {
let localTimeZoneFormatter = DateFormatter()
localTimeZoneFormatter.dateFormat = "ZZZZZ"
return localTimeZoneFormatter.string(from: Date())
}
Will return "+01:00" format
extension TimeZone {
func offsetFromUTC() -> String
{
let localTimeZoneFormatter = DateFormatter()
localTimeZoneFormatter.timeZone = self
localTimeZoneFormatter.dateFormat = "Z"
return localTimeZoneFormatter.string(from: Date())
}
func currentTimezoneOffset() -> String {
let timeZoneFormatter = DateFormatter()
timeZoneFormatter.dateFormat = "ZZZZZ"
return timeZoneFormatter.string(from: Date())
}
}
Use like this
print(TimeZone.current.offsetFromUTC()) // output is +0530
print(TimeZone.current.currentTimezoneOffset()) // output is "+05:30"
it working 100% in all countries according to timezone.
Swift 4 and above
extension TimeZone {
func timeZoneOffsetInHours() -> Int {
let seconds = secondsFromGMT()
let hours = seconds/3600
return hours
}
func timeZoneOffsetInMinutes() -> Int {
let seconds = secondsFromGMT()
let minutes = abs(seconds / 60)
return minutes
}
}
The accepted answer does not handle the case "-00:30" correctly since the "+/-" is only being determined from the hours, and not the minutes. I would set the sign based on a check of the initial seconds value. Alternatively you could use DateComponentsFormatter.
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second]
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
let interval: TimeInterval = TimeInterval.init(abs(secondsOffset))
let offsetValue: String = formatter.string(from: interval)

Swift time being returned as am when it is pm

This function gets current time and finds the next time in an array. When the current time is before midday and the next time is after midday, it returns the next time as am when it should be pm.
How can I change this? Would I need to use a 12 hour clock instead of a 24 hour clock?
import UIKit
import Foundation
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Hour, .Minute], fromDate: date)
let hour = components.hour
let minutes = components.minute
let currentTime = "\(hour)" + ":" + "\(minutes)" //output 10:47
let timesArray = ["5:45", "6:35", "7:00", "7:30", "7:50", "8:20", "8:40", "9:15", "10:10",
"12:40", "14:15", "14:50", "15:40", "16:10", "17:10", "17:40", "18:40", "19:25", "20:50"]
// create a method to convert your time to minutes
func stringToMinutes(input:String) -> Int {
let components = input.componentsSeparatedByString(":")
let hour = Int((components.first ?? "0")) ?? 0
let minute = Int((components.last ?? "0")) ?? 0
return hour*60 + minute
}
//create an array with the minutes from the original array
let timesMinutesArray:[Int] = timesArray.map { stringToMinutes($0) }
let dayMinute = stringToMinutes(currentTime)
// filter out the times that has already passed
let filteredTimesArray = timesMinutesArray.filter{$0 > dayMinute }
// get the first time in your array
if let firstTime = filteredTimesArray.first {
// find its position and extract it from the original array
let nextDeparture = timesArray[timesMinutesArray.indexOf(firstTime)!] // output "12:40"
let userCalendar = NSCalendar.currentCalendar()
let dateMakerFormatter = NSDateFormatter()
dateMakerFormatter.calendar = userCalendar
dateMakerFormatter.dateFormat = "yyyy/MM/dd"
// How many hours and minutes between current time and next departure?
dateMakerFormatter.dateFormat = "h:mm"
let startTime = dateMakerFormatter.dateFromString(currentTime)!
let endTime = dateMakerFormatter.dateFromString(nextDeparture)! //this comes back as 12:40 am not pm
let hourMinuteComponents: NSCalendarUnit = [.Hour, .Minute]
let timeDifference = userCalendar.components(
hourMinuteComponents,
fromDate: startTime,
toDate: endTime,
options: [])
let difference = (timeDifference.hour*60) + (timeDifference.minute)
}
Try a capital H in your dateFormat:
dateMakerFormatter.dateFormat = "H:mm"