I'm currently saving some timestamped data in the minutes format, eg 550 is 9:10AM.
Is there a way to convert this into the string "09:10"? I'll be using 24hr format.
I'm using swift for an iOS app, but if there is logic that's non-language specific, that would be helpful too.
Cheers,
Josh
The question is what the 550 really represents:
If it represents an abstract time interval, measured in minutes, you would likely convert it to a TimeInterval and then use DateComponentsFormatter to prepare a string representation of hours and minutes:
let timeInterval = TimeInterval(minutes * 60)
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute]
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
let string = formatter.string(from: timeInterval)
This is a simple “hours and minutes” representation. This pattern is especially useful if the number of hours could exceed 24 (e.g. 1,550 minutes is 25 hours and 50 minutes, or 1 day, 1 hour, and 50 minutes, depending upon whether you add .day to allowedUnits or not).
If, however, you really mean that the 550 minutes is intended to literally represent the time of the day, then you might use calendrical date calculations and use DateFormatter for a string representation of the time:
let timeInterval = TimeInterval(minutes * 60)
let date = Calendar.current.startOfDay(for: Date()).addingTimeInterval(timeInterval)
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "HH:mm"
let string = formatter.string(from: date)
But, that having been said, if this really represented 9:10am in the morning (not an abstract time interval nine hours and ten minutes) and you wanted to show it in the UI, you would generally honor the device’s preferred time format (am/pm or 24-hour clock):
let timeInterval = TimeInterval(minutes * 60)
let date = Calendar.current.startOfDay(for: Date()).addingTimeInterval(timeInterval)
let formatter = DateFormatter()
formatter.timeStyle = .short
formatter.dateStyle = .none
let string = formatter.string(from: date)
Either way (forcing 24 hour clock or honor the user’s preferences), though, you really are displaying a time of day, which means that this while it will be 9:10am most days of the year, if you do this on the day that we spring forward to daylight savings, it will say 10:10am, but if on the day we fall backwards back to standard time on that day, it would be 8:10am.
Clearly, the syntax is different in Objective-C than it is in Swift, but the basic API is the same (though you obviously would be using the NS prefixes, e.g. NSDateComponentsFormatter and/or NSDateFormatter).
Related
I've looked around and people have had problems with different years, random and changing results, and nil dates, but nothing like what I have, so I am asking here. Note I am in Playground right now.
I am taking strings in the format of "yyyy-mm-dd" and converting them to a different date format. Here is the code:
let example = "2001-11-03"
let dateFormatterInput = ISO8601DateFormatter()
dateFormatterInput.formatOptions = [.withFullDate, .withDashSeparatorInDate]
let date = dateFormatterInput.date(from: example)
let dateFormatterOutput = DateFormatter()
dateFormatterOutput.dateFormat = "MMMM dd, yyyy"
let output = dateFormatterOutput.string(from: date!)
The sidebar in Playground shows that the first reference to the previous day's date happens on the let date line. Also, this behavior happens on every date I've tried. In this example, it returns "November 2, 2001." I've tried different months, days, and years (1900s and 2000s) and it gives me the same result every time.
What am I doing wrong?
The key thing here is that ISO8601DateFormatter by default thinks that the time zone of your date string is GMT:
ISO8601DateFormatter.timeZone:
The time zone used to create and parse date representations. When unspecified, GMT is used.
However, the timeZone of DateFormatter by default (and also the side bar of the playground) assumes your device's local time zone:
DateFormatter.timeZone
The time zone for the receiver. If unspecified, the system time zone is used.
If your system time zone has a negative UTC offset on the start of the day 2001-11-03 UTC, then when seen from your time zone, that moment is actually in the day 2001-11-02. Hence the output you see.
Assuming you don't care about the actual value of date, and just care about the final string output, you can just set the timeZone of DateFormatter to GMT:
dateFormatterOutput.timeZone = TimeZone(identifier: "GMT")
Side note: You should also set locale when using a fixed format to avoid localisation issues:
dateFormatterOutput.locale = Locale(identifier: "en_US_POSIX")
Or better, just use one of the built-in, locale sensitive formats instead:
dateFormatterOutput.dateStyle = .medium
dateFormatterOutput.timeStyle = .none
I have a bunch of Date objects that I want to perform calculations on, for these calculations I dont need second precision so I am attempting to "zero out" the seconds on my Dates. This all works fine unless the Date already has zero seconds in which case Swift decrements the number of minutes by one, e.g 10:30:00 -> 10:29:00.
My code:
let calendar = Calendar.current
var minuteComponent = DateComponents()
minuteComponent.second = 0
let dateDelta = calendar.nextDate(after: date, matching: minuteComponent, matchingPolicy: .nextTime, direction: .backward)
I have tried all the matching policies only to get the same result.
This seems odd to me, as the target is already at the required value, though I suspect it is inline with the documentation.
Is this an appropriate way to zero out the seconds while preserving the higher magnitude components or is there a better way?
One option is to use a date formatter, since this cuts off the seconds it will be the same as rounding down.
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm"
let noSeconds = formatter.date(from: formatter.string(from: someDate))
And here is a similar solution using Calendar & DateComponents
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: someDate)
let noSeconds = calendar.date(from: components)
I want to create two variables - one with today's day of the week (Monday - Sunday) and one with the current time. I want to do more than just display it in a label, but am just trying that for now.
I tried this, but my app crashes:
let weekDay = NSCalendar.current.component(.weekday, from: Date())
self.weekDayLabel.text = "\(weekDay)"
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "EEEE"
let dayInWeek = formatter.string(from: date)
how can i return a NSDate in a predefined time zone from a string
let responseString = "2015-8-17 GMT+05:30"
var dFormatter = NSDateFormatter()
dFormatter.dateFormat = "yyyy-M-dd ZZZZ"
var serverTime = dFormatter.dateFromString(responseString)
println("NSDate : \(serverTime!)")
the above code returns the time as
2015-08-16 18:30:00 +0000
The date format has to be assigned to the dateFormat property of the date formatter instead.
let date = NSDate.date()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let str = dateFormatter.stringFromDate(date)
println(str)
This prints the date using the default time zone on the device. Only if you want the output according to a different time zone then you would add for example
Swift 3.*
dateFormatter.timeZone = NSTimeZone(name: "UTC")
Swift 4.*
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
also refer link http://www.brianjcoleman.com/tutorial-nsdate-in-swift/
how can i return a NSDate in a predefined time zone?
You can't.
An instance of NSDate does not carry any information about timezone or calendar. It just simply identifies one point in universal time.
You can interpret this NSDate object in whatever calendar you want. Swift's string interpolation (the last line of your example code) uses an NSDateFormatter that uses UTC (that's the "+0000" in the output).
If you want the NSDate's value as a string in the current user's calendar you have to explicitly set up a date formatter for that.
Swift 4.0
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
If you always have the same time zone for the input string, you can create two date formatters to output the local time zone (or a specified one):
let timeFormatterGet = DateFormatter()
timeFormatterGet.dateFormat = "h:mm a"
timeFormatterGet.timeZone = TimeZone(abbreviation: "PST")
let timeFormatterPrint = DateFormatter()
timeFormatterPrint.dateFormat = "h:mm a"
// timeFormatterPrint.timeZone = TimeZone(abbreviation: "EST") // if you want to specify timezone for output, otherwise leave this line blank and it will default to devices timezone
if let date = timeFormatterGet.date(from: "3:30 PM") {
print(timeFormatterPrint.string(from: date)). // "6:30 PM" if device in EST
} else {
print("There was an error decoding the string")
}
The number 1 means 1 regardless of language. Yet in English it's spelled as one, in Spanish it's una, in Arabic it wahid, etc.
Similarly 123982373 seconds pass 1970 is going to reflect differently in different timezones or calendar formats, but's all still 123982373 seconds passed 1970
The difference between 3 seconds and 7 seconds is 4 seconds. That doesn't require a calendar. Neither you need a calendar/timezone to know the difference in time between these two Epoch times 1585420200 and 1584729000
Dates are just a timeInterval from January 1, 1970 (midnight UTC/GMT). Dates also happen to have a string representation.
Repeating Nikolia's answer, Swift's default string interpolation (2015-08-16 18:30:00 +0000) uses a DateFormatter that uses UTC (that's the "+0000" in the output).
Calendars with the use of timezones give us a contextual representation that is just easier to understand than trying to calculate the difference between two gigantic numbers.
Meaning a single date (think of a single timeInterval since 1970) will have a different string interpretations per calendar. On top of that a calendar will itself vary based on time zones
I highly recommend that you go and play around with this Epoch converter site and see how selecting a different timezone will cause the string representations for the same moment/date/timeInterval to change
I also recommend to see this answer. Mainly this part:
Timezone is just an amendment to the timestamp string, it's not considered by the date formatter.
To consider the time zone you have to set the timeZone of the formatter
dateFormatter.timeZone = TimeZone(secondsFromGMT: -14400)
I'm trying to convert the UNIX epoc time to datetime format using the below code
var epocTime = NSTimeInterval(1429162809359)
let myDate = NSDate(timeIntervalSince1970: epocTime)
println("Converted Time \(myDate)")
the actual result is (Thu, 16 Apr 2015 05:40:09 GMT) but am getting something like (47258-05-14 05:15:59 +0000) Can anyone please tel me how to achieve this.
update: Xcode 8.2.1 • Swift 3.0.2 or later
You need to convert it from milliseconds dividing it by 1000:
let epochTime = TimeInterval(1429162809359) / 1000
let date = Date(timeIntervalSince1970: epochTime) // "Apr 16, 2015, 2:40 AM"
print("Converted Time \(date)") // "Converted Time 2015-04-16 05:40:09 +0000\n"
Swift 5
I am dealing with a date in a JSON api which is defined as an Int and an example of the timestamp is 1587288545760 (UTC)
The only way I could display that value as a Date in a way that made any sense was to truncate the last 3 digits and convert THAT resultant date to "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
This was the function I created to achieve that.
func convertDate(dateValue: Int) -> String {
let truncatedTime = Int(dateValue / 1000)
let date = Date(timeIntervalSince1970: TimeInterval(truncatedTime))
let formatter = DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "UTC")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
return formatter.string(from: date)
}
It works for me and I end up with a date that looks like this:
"2020-04-19T09:29:05.000Z"
..and it reflects the fact that the original time stamp is exactly that date.
Hope that helps anyone having the same issue.
It seems that your time information is "milliseconds since 1970". Should have been straightforward to figure out: We are about 46 years after 1970, but your date is about 45,000 after 1970.
NSTimeInterval is based on SECONDS.
Convert your number to double and divide by 1000.0.