Applying NSDate from server with localtimezone get NSDate - objective-c

I'm returning an NSDate from my server (running on GMT+2)
I'm calculating few things with the server's date and the device current date.
The problem (obviously) is when the device is running on different timezone then my server.
How can I apply and change the server's NSDate to return current device NSDate for my calculation will be exact for every time zone.
I simply need a function that will get my server NSDate with my server's timezone (gmt+2) and will return the correct device NSDate.
hope someone can help me on that
Server returns Ticks (running on c#) and manipulating to nsdate with this code
double tickFactor = 10000000;
double ticksDoubleValue = [ticks doubleValue];
double seconds = ((ticksDoubleValue - 621355968000000000)/ tickFactor);
NSDate *returnDate = [NSDate dateWithTimeIntervalSince1970:seconds];
return returnDate;

The NSDate class stores an absolute time. To facilitate this, it represents time in UTC, which is time-zone-agnostic. However you create an NSDate, it is assumed the time is in UTC. Even when you use NSDateFormatter to "read" a date from a string, it's just doing the math on your behalf, before creating the NSDate.
If you have a time representation that includes a time zone offset, you need to account for that when you do the conversion. As mentioned above, given a proper format string, NSDateFormatter will do that for you. If your representation is numeric (typically number of seconds from some date), you need to add or subtract the time zone offset. Add if the offset is negative, subtract if it's positive.
To adjust a server date provided in the server's local time, adjust based on the server's time zone. For GMT+2, subtract 3600 * 2 (number of seconds per hour * offset). This gives the seconds in UTC. When you create the NSDate using `[NSDate dateWithTimeIntervalSince1970:]. it will be the expected time.

Related

How to get/convert UTC date from local Date in OSX?

I need to get UTC date by specified NSDate.
The problem is that utcDate doesn't calculates properly if date was in daylight saving period.
Here is a code I use:
NSDate *localDate = [updatesInfo objectForKey:#"date"];
NSTimeInterval timeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
NSTimeInterval gmtTimeInterval = [localDate timeIntervalSinceReferenceDate] - timeZoneOffset;
NSDate *utcDate = [NSDate dateWithTimeIntervalSinceReferenceDate:gmtTimeInterval];
UPD:
I read localDate from /Library/Receipts/InstallHistory.plist It's an OSX file which contains all application's installation history.
https://www.dropbox.com/s/3pc178avr4pj7uj/1.png?dl=0
NSDate is in UTC. Always.
The code that you posted seems to indicate that your "updatesInfo" contains an incorrect NSDate. Or at least you think it contains an incorrect date.
You may have made a mistake when you created the date. As a partial workaround, you can try using secondsFromGMTForDate: which will be correct most of the time, except for some dates very close to the point where DST changed (because the date you have isn't correct). You can improve on that:
NSTimeInterval timeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMTForDate:localDate];
NSDate* betterDate = [localDate dateByAddingTimeInterval: -timeZoneOffset];
timeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMTForDate:betterDate];
NSDate* utcDate = [localDate dateByAddingTimeInterval: -timeZoneOffset];
A property list file stores a date in UTC. If you open the file in a plain text
editor you will see something like
<key>date</key>
<date>2014-07-08T09:30:15Z</date>
which is "2014-07-08 09:30:15 UTC". Therefore
NSDate *date = [updatesInfo objectForKey:#"date"];
should contain the correct date and there is no need to adjust that for your local
time zone.
But note that the Xcode property list editor displays the date stored in the property list file according to your local time zone. And if you edit a date field in Xcode,
it will be translated back to UTC for storage in the plist file.

Remove time from NSDate object and save it in NSDate not in string?

There are lot of questions about date and time, but my question is a bit different.
Why NSDate comes with times added to it?
Why can not time be removed from NSDate? I can remove the time but it needs to be saved in String, Why it is not allowed to save it in NSDate?
NSDate actually stores a number of seconds from reference date (Jan 1, 2001). Everything rest are calendar calculations based on this amount of seconds. If you truncate time components and store result as 'NSDate' you will have different dates on different time zones.
You should consider using NSDateFormatter to convert NSDate values to string. Use:
[formatter setDateStyle:NSDateFormatterMediumStyle];
[formatter setTimeStyle:NSDateFormatterNoStyle];
to setup date formatter to ignore time.
Is this what you were looking for?
func dayOf(date: NSDate) -> NSDate {
return NSCalendar.currentCalendar().dateBySettingHour(0, minute: 0, second: 0, ofDate: date, options: NSCalendarOptions())!
}
A reusable way to solve this problem in swift is writing an extension on NSDate to trim the time off of the object.
import Foundation
extension NSDate {
func trimTime() -> NSDate {
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let components = cal.components([.Day, .Month, .Year], fromDate: self)
return cal.dateFromComponents(components)!
}
}
This is not possible to remove TimeStamp from NSDate. NSDate is always packed with timestamp.
NSDate is based on the UTC time zone. If it is 1AM in US, it will be 12:30 PM in some other country and the date will be different. It will become trouble to get who entered when if different dates are there. So to make the date consistent timestamp-ing is required.
EDIT:
UTC update as suggested by Zaph :)
tiemstamp as suggested by Daij-Djan
NSDate is a presentation way of time stamp, you can get different date with different timezone of the same NSDate object, so you cannot just save the "date" part of NSDate object, that's not the way NSDate works.
If you don't want time present in date string, just format it without time.
My suggestion is save time stamp in your database, if you need to find certain date, use a range query, that way you can deal with timezone problem.
Timezone function is hard to implement with date field.

How can I see that a real world time has passed from a stored start date in obj-c/ios?

In my game players will be able to plant a tree, which will take 3 hours to grow. When the player logs back in how would I calculate whether that tree is now fully grown? the creation date of the tree (planted) will be stored on a server, and I will be storing the 3 hours in seconds (not sure if that should be an int of NSNumber) also on the server.
Thanks for any help.
Get your creation date back from the server as an NSDate, and use timeIntervalSinceDate: like so:
NSDate *now = [NSDate date];
NSTimeInterval secondsSincePlanting = [now timeIntervalSinceDate:plantingDate];
if (secondsSincePlanting > secondsRequiredForTreeToFullyGrow) {
...
}

using NSDate to find the DATE from string

I am having problem finding date from string that is formatted using NSDateFormatter
Now, I am using this code:
NSDate *afterDate=[NSDate dateWithNaturalLanguageString:balanceDateAfter.stringValue];
This code returning date with GeorgianCalendar format but I want it in PersianCalendar.
I think if I use this code :
NSDate *afterDate=[NSDate dateWithNaturalLanguageString:balanceDateAfter.stringValue locale:];
It will return true date format but I don't know how can I use locale to set appropriate date formatter ( or my system locale ).
balanceDateAfter in above codes is an NSTextfield with NSDateFormatter.
NSDates do not have a calendar. An NSDate represents an absolute moment in time as defined by the difference between that moment and the first instant of 1st January 2001 in GMT. Basically, it's a positive or negative number of seconds, nothing more.
If you have an appropriate formatter assigned to the text field, you should get its value using -objectValue, not -stringValue. That way, you will be given the NSDate directly and you won't need to parse the string yourself.

Converting JSON date(ticks) to NSDate

Does anyone know how to convert a JSON date(ticks) to an NSDate in Objective-C? Can someone post some code?
I'm guessing here but your JSON value is the number of milliseconds since 1970, right? You can use NSDate's dateWithTimeIntervalSince1970: method to return an NSDate object with the correct time. Just make sure to convert the JSON milliseconds number to seconds before passing it to NSDate-- Cocoa uses NSTimeInterval in most places, which represents an interval in seconds.
It goes roughly like this:
// Input string is something like: "/Date(1292851800000+0100)/" where
// 1292851800000 is milliseconds since 1970 and +0100 is the timezone
NSString *inputString = [item objectForKey:#"DateTimeSession"];
// This will tell number of seconds to add according to your default timezone
// Note: if you don't care about timezone changes, just delete/comment it out
NSInteger offset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
// A range of NSMakeRange(6, 10) will generate "1292851800" from "/Date(1292851800000+0100)/"
// as in example above. We crop additional three zeros, because "dateWithTimeIntervalSince1970:"
// wants seconds, not milliseconds; since 1 second is equal to 1000 milliseconds, this will work.
// Note: if you don't care about timezone changes, just chop out "dateByAddingTimeInterval:offset" part
NSDate *date = [[NSDate dateWithTimeIntervalSince1970:
[[inputString substringWithRange:NSMakeRange(6, 10)] intValue]]
dateByAddingTimeInterval:offset];
(from https://gist.github.com/726910)
You'd have to detect the client's locale in order to be able to do that, and unless your client knows how to do that, there's probably not much point.
NSDate's descriptionWithLocale: would be the way you format it for another locale. And timeIntervalSince1970 will go back to the (seconds) since 1970, which you could multiply by 1000 to get ms to return to the client. It's all in the NSDate documentation.
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/Reference/Reference.html
According to this page: http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx ticks begin on Jan 1, 0001 so dateWithTimeIntervalSince1970: is not automatically setup to work with ticks. You can still use this method but should adjust for the difference.