I'm trying to format to MM:SS using NSDateComponentsFormatter:
let formatter = NSDateComponentsFormatter()
formatter.zeroFormattingBehavior = .Pad
formatter.allowedUnits = .CalendarUnitMinute | .CalendarUnitSecond
let time: NSTimeInterval = 5
let timeText = formatter.stringFromTimeInterval(time)
The problem is, that even though I specified .Pad, the result is 0:05 instead of 00:05.
Here's the relevant piece from Apple's documentation:
static var Pad: NSDateComponentsFormatterZeroFormattingBehavior { get }
// Off: "1:0:10", On: "01:00:10"
I've tried to add .CalendarUnitHour just to try it and got H:MM:SS instead of HH:MM:SS despite what the documentation says.
How can I pad the very first number as shown in the documentation?
Sorry for wrong initial answer, there is no way to add leading zeros to hours:
When days, hours, minutes, and seconds are allowed, the value is displayed as “0d 1:00:00” using the positional style, and as “0d 1h 0m 0s” using the abbreviated style.
If you simply need to format NSTimeInterval into string like HH:MM:SS check this answer
Related
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 using a NSDateComponentFormatter to print durations, like so:
/// Hour-Minute duration formatter (abbreviated, localized, eg. 6h 22m)
let hourMinuteDurationFormatter: DateComponentsFormatter = {
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.unitsStyle = .abbreviated
dateComponentsFormatter.zeroFormattingBehavior = .pad
dateComponentsFormatter.allowedUnits = [.hour, .minute]
return dateComponentsFormatter
}()
This works fine in most of the cases.
For example, I can print duration strings like "6h 56mn"
However, if the number of minutes is less than 10, I get this kind of strings: "6h 3mn"
As I'm using these duration strings in a table, I'd like them to be formatted consistently, that is, keeping all zeroes.
For instance, I'd like to have "6h 03mn".
NB: Yes, NSDateFormatter has a dateFormat property to format dates/time like "HH:mm" or "HH'h 'mm'mn' ", but it doesn't work with durations.
And I haven't found a formatter for durations except NSDateComponentsFormatter.
Thanks
Following piece of code in Swift to generate time stamp of current time, but sometime it gives wrong output like different Year 2016 instead of 2015.
let todaysDate: NSDate = NSDate()
let dateFormatter:NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
var currentTimeStamp = dateFormatter.stringFromDate(todaysDate)
print("** Current time stamp: " + currentTimeStamp)
I don't understand why does same piece of code give different output?
This was fixed for me by changing YYYY to yyyy as suggested by BhavukJain in the comments.
From https://8mobile.wordpress.com/2015/05/28/nsdateformatter-nsdate-wrong-year/
y = Year, normally the length specifies the padding, but for two letters it also specifies the maximum length.
Y = Year (in “Week of Year” based calendars), this year designation is used in ISO year-week calendar as defined by ISO 8601, but can be used in non-Gregorian based calendar systems where week date processing is desired. May not always be the same value as calendar year.
Basically what I want is to get the value of a time interval represented in hours only, without rounding it to full hours (using NSDateComponentsFormatter to get it properly formatted and localized). I don't know if I misunderstand the use of NSDateComponentsFormatter.allowsFractionalUnits, but I can't get the formatter to give me a decimal value. Can anyone help me spot my error or tell me in what way I misunderstand this?
From Apple docs about allowsFractionalUnits property:
Fractional units may be used when a value cannot be exactly
represented using the available units. For example, if minutes are not
allowed, the value “1h 30m” could be formatted as “1.5h”.
Swift example code:
let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = .Abbreviated
formatter.allowedUnits = .Hour
formatter.allowsFractionalUnits = true
let onePointFiveHoursInSeconds = NSTimeInterval(1.5 * 60.0 * 60.0)
print(formatter.stringFromTimeInterval(onePointFiveHoursInSeconds)!)
//"1h" instead of expected "1.5h"
Same example in Objective-C code:
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleAbbreviated;
formatter.allowedUnits = NSCalendarUnitHour;
formatter.allowsFractionalUnits = YES;
NSTimeInterval onePointFiveHoursInSeconds = 1.5 * 60.0 * 60.0;
NSLog(#"%#", [formatter stringFromTimeInterval:onePointFiveHoursInSeconds]);
//"1h" instead of expected "1.5h"
Update:
I have reported a bug to Apple about this problem (rdar://22660145).
According to Open Radar #32024200:
After doing some digging (disassembling Foundation), it looks like every call to -[_unitFormatter stringFromNumber:] in -[NSDateComponentsFormatter _stringFromDateComponents:] is passed an +[NSNumber numberWithInteger:] which drops floating point data.
You're not doing anything wrong. The flag is simply broken.
Looking at the documentation, it’s using a lot of interesting language (emphasis mine):
Fractional units may be used when a value cannot be exactly represented using the available units. For example, if minutes are not allowed, the value “1h 30m” could be formatted as “1.5h”.
While to me it seems that it would only make sense for the values in the documentation to be values that actually work, it’s certainly possible that there is some combination of time value, formatter options, and calendar/locale settings that would make this work. Definitely worth filing a Radar on both the functionality and the documentation.
enter code hereAs far as i understood , You want to display time in 12-Hour formate Right ?
Below is the code :
Swift->
let dateAsString = "20:30"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "HH:mm"
let date = dateFormatter.dateFromString(dateAsString)
dateFormatter.dateFormat = "h:mm a"
let date12 = dateFormatter.stringFromDate(date!)
txtText.text = date12
I am writing an app which need to show dates with corresponding time symbols like "hours", "minutes" etc.
There are cool localized constants for months and weekdays names in NSDateFormatter like monthSymbols (January, February etc). However, I can't find anything like this for such symbols as "hour", "minute" itself. Does such constants exists or I should create and localize these symbols by myself?
UPD:
My goal is a text for label under "30" - only localized "MIN" string without any numbers I should get rid of before placing text from date formatter in the label at the bottom.
Depending on the details of what you need, NSDateComponentsFormatter might be the solution. It includes NSDateComponentsFormatterUnitsStyleSpellOut, which renders strings in formats like “One hour, ten minutes”.
Update: After reading comments I'm still not sure what kind of formatting you really need. But hopefully this will be a useful example:
let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyle.Full
formatter.allowedUnits = [ NSCalendarUnit.Minute, NSCalendarUnit.Hour ]
let date = NSDate()
let dateComponents = NSCalendar.currentCalendar().components([.Minute, .Hour], fromDate: date)
let dateString = formatter.stringFromDateComponents(dateComponents)
At this point, dateString will be something like "15 hours, 11 minutes".
If you need just the min string localized you can use a MeasurementFormatter()
let measurementFormatter: MeasurementFormatter = {
let measurementFormatter = MeasurementFormatter()
measurementFormatter.locale = Locale.current
measurementFormatter.unitOptions = .providedUnit
measurementFormatter.unitStyle = .short
return measurementFormatter
}()
label.text = measurementFormatter.string(from: UnitDuration.minutes)