Timestamp to weekday going wrong - swift

I made this function:
func getDayOfWeek(date: NSDate) -> String? {
let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let myComponents = myCalendar?.components(NSCalendarUnit.CalendarUnitWeekday, fromDate: date)
let weekDay = myComponents?.weekday
println(date)
return weekNumberToWord(weekDay!)
}
To which I give a timestamp as date (1439460000, which is the date of today) and it prints: 2046-08-13 10:00:00 +0000. How is this possible?
This is how I call the function:
var day = getDayOfWeek(NSDate(timeIntervalSinceReferenceDate: timestamp.doubleValue))!
In which getDayOfWeek() is a switch converting all the numbers to day name as string.

You are using the wrong initializer:
init(timeIntervalSinceReferenceDate:)
Returns an NSDate object initialized relative the first instant of 1 January 2001, GMT by a given number of seconds.
You should use init(timeIntervalSince1970 seconds: NSTimeInterval) to initialize a date from a UNIX timestamp (which you are apparently using):
Returns an NSDate object set to the given number of seconds from the first instant of 1 January 1970, GMT.
var day = getDayOfWeek(NSDate(timeIntervalSince1970: timestamp.doubleValue))!

Related

Swift date components incorrect return of date day number

I need to obtain a date from some variable values
So I specify year, month and day and I need a Date as return
Doing the following works except for the day because it return the day input - 1
let todayDate: Date = Calendar.current.startOfDay(for: Date.from(year: 2022, month: 09, day: 05)!)
print("today date = \(todayDate)")
extension Date {
static func from(year: Int, month: Int, day: Int) -> Date? {
let calendar = Calendar(identifier: .gregorian)
var dateComponents = DateComponents()
dateComponents.year = year
dateComponents.month = month
dateComponents.day = day
return calendar.date(from: dateComponents) ?? nil
}
}
And the output is
today date = 2022-09-04 22:00:00 +0000
Date and time can be a bit tricky. The Date struct stores a point in time relative to GMT. If you print it it will show exactly that.
Solution:
Don´t use print, use a proper Dateformatter. To illustrate what I mean use this in a playground:
let date = Calendar.current.startOfDay(for: Date())
print(date)
//2022-09-03 22:00:00 +0000
// when it is 4.th of september 00:00 in my timezone (+- Daylight saving) it is this time in GMT
let formatter = DateFormatter()
formatter.dateFormat = "dd MM yyyy HH:mm:ss"
print(formatter.string(from: date))
//04 09 2022 00:00:00
// this is the time in my timezone
So the issue here is not that it has the wrong time, it is just not presented in the correct time zone.

How to parse date in "2022-03-04T10:30:00-08:00" format correctly in swift?

I have date coming from API shown below. These dates are for different countries.
dateTime = "2022-03-04T14:30:00-08:00"
I need to convert this use it both as Date and as String. But I do not know if date and time I am converting are correct. I am using following code:
To Convert String from API to Date:
extension String {
var CommonDateFormat: Date? {
get {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
return dateFormatter.date(from: self)
}
}
}
To Convert Date to String:
extension Date {
func getDateAccoringTo(format: DateFormat ) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format.rawValue
dateFormatter.timeZone = .current
dateFormatter.timeZone = TimeZone.init(identifier: "UTC")
return dateFormatter.string(from: self)
}
}
enum DateFormat: String {
case ddmmyyyy = "dd/MM/yyyy"
case mmddyyyy = "MM/dd/yyyy"
case mmmd_yyyy = "MMM d, yyyy"
case llll_yyyy = "LLLL ,yyyy"
case TIME = "HH:mm:ss"
case day = "dd"
}
When I try to get day from date it always gives next day date. For example if date = "2022-03-04T14:30:00-08:00" then if I try to get day using code below
date?.getDateAccoringTo(format: .day)
This returns 5 not 4
date?.getDateAccoringTo(format: .TIME)
This returns time 00:00:00
Am I missing something important which is leading to these values?
Also, if I am missing something in my question kindly let me know so that I can improve it.
The given string
let dateTime = "2022-03-04T14:30:00-08:00"`
is a standard ISO8601 formatted date string. It can be converted to Date with
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: dateTime)!
At this specific point in time it is
14:30 on Friday, March 4 in Denver, CO, USA
22:30 on Friday, March 4 in London, UK
06:30 on Saturday, March 5 in Tokyo, Japan
Now let's see how Xcode displays dates.
print displays Date instances always in UTC indicated by +0000 which is the London time zone unless you print(date.description(with: .current), this displays the date in the local time zone.
In a Xcode Playground the result area displays Date instances in the local time zone except in print lines.
Last point to consider is that DateFormatter converts Date to String in the local time zone if no time zone is specified.
Keeping this behavior in mind you get the next day if you convert the date to string with DateFormatter but without specifying the time zone and your local time zone is greater than or equal to +01:30.
And you get the time 00:00 if you convert the date to string with DateFormatter but without specifying the time zone and your local time zone is exactly +01:30 which is a pretty unusual time zone by the way.

Swift 5 Datetime Conversion triple timezone cast (???)

I have a DateTime that I'm reading from an API that is in GMT.
I want to force cast it to an EST date object.
The original object is a string that I then cast to a Date to do some time comparison. Unfortunately, I don't think I did this right which made me do this unholy abomination:
extension String {
//this force casts from our original data being in GMT to EST
func getDateTimeTZ() -> Date{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
if let date = dateFormatter.date(from: self) {
dateFormatter.timeZone = TimeZone(abbreviation: "EST")
let localTime = dateFormatter.string(from: date)
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
return dateFormatter.date(from: localTime)!
}
return dateFormatter.date(from: self)!
}
}
For whatever reason, I seem to have to flip the dateformatter 3 times to get the correct EST string output. Is there a better way to do this?
A Date is not associated with a time zone. From the Date reference:
A specific point in time, independent of any calendar or time zone.
...
A Date value encapsulate a single point in time, independent of any particular calendrical system or time zone. Date values represent a time interval relative to an absolute reference date.
So there is no such thing as “an EST date object” in the iOS SDK.
Time zones are relevant when converting to or from strings and when manipulating the calendrical components (year, month, day, hour, minute, second, etc.) of a Date.
The code you posted computes a new Date that is offset from the original date by the time offset between GMT and EST, but the new Date is not “an EST date object”.
(Incidentally, "EST" means Eastern Standard Time, and will not switch to daylight saving time during the appropriate part of the year. Use "US/Eastern" to get the appropriate time conversion depending on the day of year.)
You say you're doing this adjustment “to do some time comparison”, but you don't say what you're comparing to. It would help for you to describe what comparison you're performing.
For example, let's you want to check whether the Date is in the range 8:30 AM to 3:00 PM in the US/Eastern time zone, regardless of the day. If the input string is GMT, then you should parse it that way, as you do in your code:
let parser = DateFormatter()
parser.timeZone = TimeZone.init(identifier: "GMT")
parser.dateFormat = "yyyy-MM-dd HH:mm"
let date = parser.date(from: "2021-03-26 19:55")!
Then, use a Calendar set to the "US/Eastern" TimeZone to compute the hour and minute components of the Date:
var calendar = Calendar.current
calendar.timeZone = TimeZone(identifier: "US/Eastern")!
let components = calendar.dateComponents([.hour, .minute], from: date)
let hhmm = components.hour! * 100 + components.minute!
if (08_30 ..< 15_00).contains(hhmm) {
print("school time")
} else {
print("play time")
}

What time/day format is openweathermap.org list.dt using

I'm using the day forecast api at http://openweathermap.org/forecast16. There is a parameter called list.dt. It gives a value in this format: 1406080800.
What format is that and how would I translate it to some human readable using functionality in Swift?
The date is most likely in unix time (see forecast5, which states that list.dt is the "Time of data forecasted, unix, UTC".
Using Swift, you can use NSDate(timeIntervalSince1970: dt) in order to convert this to a date. Then you can use standard NSDateFormatter to make it human readable.
The dt is for date and time.
The value of dt is in a format known as unix time
Unix time is a system for describing time, which is the number of seconds elapsed since 00:00:00 (UTC), Thursday, 1 January 1970.
The value you have there (1406080800) is equal to Wed, 23 Jul 2014 02:00:00 GMT which is used in there example provided for the link you posted.
To use within Swift try the following:
var date = NSDate(timeIntervalSince1970: timeInterval)
To get a unix timestamp from Swift you can also use:
let timeInterval = NSDate().timeIntervalSince1970
Create a computed property to convert timestamp that you've got into Date. CodingKeys are here just to rename the meaningless dt.
struct Weather: Codable {
private let timestamp: Double
let temp: Float
var date: Date {
Date(timeIntervalSince1970: timestamp)
}
enum CodingKeys: String, CodingKey {
case timestamp = "dt", temp
}
}

Calculating StartDate and endDate of a day based on todays date. Swift 2

I have the following function which i am using to calculate a start and end of todays date. It was working perfectly last week, i think it may have something to do with the clocks going forwards?
func rangeOfPeriod(period: NSCalendarUnit, date: NSDate) -> (NSDate, NSDate) {
let calendar = NSCalendar.currentCalendar()
var startDate: NSDate? = nil
var duration: NSTimeInterval = 0
calendar.rangeOfUnit(period, startDate: &startDate, interval: &duration, forDate: date)
let endDate = startDate!.dateByAddingTimeInterval(duration - 1)
return (startDate!, endDate)
}
When I try and calculate the start and end of a day using:
print("Start of Day = \(rangeOfPeriod(.Day, date: NSDate()).0), End of Day = \(rangeOfPeriod(.Day, date: NSDate()).1)")
I get the following, where the start and end date is 1hour behind what is expected:
Start of Day = 2016-03-27 23:00:00 +0000, End of Day = 2016-03-28 22:59:59 +0000
when i would expect:
Start of Day = 2016-03-28 00:00:00 +0000, End of Day = 2016-03-28 23:59:59 +0000
Any help would be appreciated