Zoned dateTime to UTC Time - LocalDateTimePattern throws exception - timezone

I am trying to obtain the UTC time from a zoned datetime using LocalDateTime pattern in NodaTime using the below code.
public string getUtcTimeFromZonedTime(string dateTimeString, string timeZoneID,
string dateTimePattern, bool isDateTime)
{
if (string.IsNullOrEmpty(dateTimePattern))
{
if (isDateTime)
{
dateTimePattern = "M/dd/yyyy HH:mm:ss tt";
}
else
{
dateTimePattern = "M/dd/yyyy";
}
}
var pattern = LocalDateTimePattern.CreateWithInvariantCulture(dateTimePattern);
var parseResult = pattern.Parse(dateTimeString);
if (!parseResult.Success)
{
// throw an exception or whatever you want to do
}
var localDateTime = parseResult.Value;
var timeZone = DateTimeZoneProviders.Tzdb[timeZoneID];
// TODO: Consider how you want to handle ambiguous or "skipped" local date/time
// values. For example, you might want InZoneStrictly, or provide your own custom
// handler to InZone.
var zonedDateTime = localDateTime.InZoneLeniently(timeZone);
return zonedDateTime.ToDateTimeUtc().ToString();
}
I get an exception during Parsing during below mentioned scenarios-
1) If pattern is like "MM/dd/yyyy HH:mm:ss tt" and the DateTime string is something like "5/28/2013 1:02:ss PM"
2) If pattern is like "MM-dd-yyyy HH:mm:ss tt" and the DateTime string is something like "5/28/2013 1:02:ss PM"
For the first case, it will work if I change my pattern to "M/dd/yyyy HH:mm:ss tt", but i will end up losing the leading zero. Second case will work if I change the pattern to "MM/dd/yyyy HH:mm:ss tt"
Is there any alternative way for getting the UTC values or am I doing something wrong over here.

1) If pattern is like "MM/dd/yyyy HH:mm:ss tt" and the DateTime string is something like "5/28/2013 1:02:ss PM"
Yes, because you've specified that you'll give it a two-digit hour, and you've only given one digit. Note that if you're using an AM/PM designator, you probably want h rather than H anyway.
2) If pattern is like "MM-dd-yyyy HH:mm:ss tt" and the DateTime string is something like "5/28/2013 1:02:ss PM"
Yes, because you've specified that you want - as the separator, but you're using / in the text.
I suspect you want:
dateTimePattern = "M/dd/yyyy h:mm:ss tt";
Note that this has nothing to do with converting to UTC - it's just the parsing to LocalDateTime that's causing you problems.

Related

Display local time zone abbreviation using DateFormatter

I have a DateFormatter that outputs the date in the format "2:00pm, Thu 18 Oct":
static func scheduleFormatter() -> DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.amSymbol = "am"
dateFormatter.pmSymbol = "pm"
dateFormatter.dateFormat = "h:mma, EE dd MMM"
return dateFormatter
}
I need to add in the local time zone abbreviation of the user so that the string appears like "2:00 pm GMT, Thu 18 Oct". How can I do that?
Look at the Unicode Date Formatting Patterns:
Probably you want the pattern v:
The short generic non-location format. Where that is unavailable, falls back to the generic location format ("VVVV"), then the short localized GMT format as the final fallback.
or z:
The short specific non-location format. Where that is unavailable, falls back to the short localized GMT format ("O").
Note that time zone names are connected to language and setting posix locale will probably break that.
You could also ask for the abbreviation directly and include it in your format explicitly:
"h:mma, '\(TimeZone.current.abbreviation() ?? "")' EE dd MMM"
To display the time zone you can simply add "zzz" in your dateFormat string. For example: "h:mma zzz, EE dd MMM"
public static Date getCurrentTimeStampDate(){
String currentDate = new SimpleDateFormat(""yyyy:MM:dd HH:mm:ss").format(Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime());
SimpleDateFormat formater = new SimpleDateFormat(""yyyy:MM:dd HH:mm:ss");
try {
return formater.parse(currentDate);
} catch (ParseException e) {
return null;
}
}

String did not Convert Properly to Date in ios Swift

I want to convert string to date everything is fine but still, it gives me an incorrect date according to string.
Code:
import UIKit
public class Utils {
public class func converServerTimeStampToDate (_ timeStamp: String) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy, hh:mm:ss a"
return dateFormatter.date(from: timeStamp)!
}
}
print(Utils.converServerTimeStampToDate("12/06/2017, 06:48:03 am"
))
-----OutPut-----
2017-12-06 14:48:03 +0000
To solve this problem set timezone
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+0:00")
By default it is taking current time zone that's why your output is different from input.
It is correct result. When you convert any string into Date it will convert it in UTC timezone. And when you convert that date into string again it will be in your current timezone. So, convert that date into string and you real date you will get. So, your Date object always be in UTC timezone and your string will be always in your local timezone. And when you displays your date in label or any other control then definitely you will display in string format and it will be in your local timezone. So, there is nothing wrong in it. You just required to understand the concept!

How to convert date of format dd MMM, yyyy into dd/MM/yyyy in mvc

I want to convert date into above mentioned format. I have used:
DateTime date1 = DateTime.ParseExact(date, "dd/MM/yyyy", null);
But it gives exception as string is not recognized as a valid date time.
Note:date is of a string datatype and it is in dd MMM, yyyy format.
string is not recognized as a valid date time
Because you're trying to parse the date string from this format:
"dd/MM/yyyy"
But, as you state, the date string is in this format:
"dd MMM, yyyy"
ParseExact means just that... exact. Parse the date from the format it's in:
DateTime date1 = DateTime.ParseExact(date, "dd MMM, yyyy", null);
Then you can output that value in any format you like:
date1.ToString("dd/MM/yyyy");
ParseExact takes the source format as second parameter. Try to use DateTime.ParseExact(date, "dd MMM, yyyy", null);.
#David beat me to the answer, but I just want to add that you should use TryParseExact rather than ParseExact. That way, you can recover from potential problems. For example:
if (DateTime.TryParseExact(date, "dd MMM, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date2))
{
date2.ToString("dd/MM/yyyy");
}
else
{
// handle date in incorrect format
}
Can yo please try this:
string dateString = "15 Jun, 2017";
DateTime result = DateTime.ParseExact(dateString, "dd MMM, yyyy", null);
// Changing to dd/MM/yyyy
string myDate = result.ToString("dd/MM/yyyy");

NSDate and string without timezone information

I am parsing some XML that is returned by a web service. The string: 2015-12-24T12:00:00 is found in the fromTimestamp with no timezone. The "geniuses" (I don't mean that) keeps the timezone information in a own field in the XML in minutes. So 300 means GMT+05:00.
I have been reading a lot about NSDate and all this timezone stuff and I know that NSDate don't care about timezones, thats NSDateFormatter job.
However, in order to "convert" the timestamp without the timezone so that the value in NSDate represents a GMT time I add the GMT+05:00 to the string so it becomes 2015-12-24T12:00:00 +05:00. This is how it must be done right? Without adding the timezone when you convert from string to date the NSDate thinks the value is the GMT time? Thats the part I don't understand about it. It would be wrong to just convert the string without that timezone information because NSDate wouldn't be able to subtract 5 hours from the value inside NSDate? Is that correct? I am having a hard time explaining it.
Your assessment is correct and your solution is one of two possible solutions.
To ensure the date string is properly converted to an NSDate, you can do one of two things:
You need to ensure the date string has timezone information included and the date formatter's format string includes the proper format specifier for the timezone. This is what you describe in your question.
You leave the date string as you have it, without timezone information. But you set a specific timezone on the date formatter based on the timezone field you get from the XML.
Either approach will give you the proper NSDate.
Update: My second approach is shown in the answer by Martin R.
It may be simpler to set the time zone of the date formatter
explicitly. Example (error checking omitted for brevity):
let fromTimestamp = "2015-12-24T12:00:00"
let timeZoneInfo = "300"
let fmt = NSDateFormatter()
fmt.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let secondsFromGMT = Int(timeZoneInfo)! * 60
fmt.timeZone = NSTimeZone(forSecondsFromGMT: secondsFromGMT)
let date = fmt.dateFromString(fromTimestamp)
I found it more convenient to wrap Martin's approach as an extension of the String class. It also prepends it with current timestamp and writes text ta a debugger output.
Swift 5:
"Hello world".log()
2019-09-05 12:18:10 Hello world
extension String {
func log() {
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd' 'HH:mm:ss"
let formattedString = "\(fmt.string(from: Date())) \(self)"
print(formattedString)
let log = URL(fileURLWithPath: "log.txt")
do {
let handle = try FileHandle(forWritingTo: log)
handle.seekToEndOfFile()
handle.write((formattedString+"\n").data(using: .utf8)!)
handle.closeFile()
} catch {
print(error.localizedDescription)
do {
try self.data(using: .utf8)?.write(to: log)
} catch {
print(error.localizedDescription)
}
}
}
}

How to convert String to NSDate?

I have string that I received whenever there is new remote notifications.I'm using parse for my Backend. And String that I retrieved come from "createdAt" column.
I've tried below code:
var ca = "2015-07-03T03:16:17.220Z"
var dateFormater : NSDateFormatter = NSDateFormatter()
dateFormater.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
let date = dateFormater.dateFromString(ca)
println(date)
But the println is giving me nil, I think there is something wrong with my date format. How can I fix this?
You are missing the milliseconds. Thus:
dateFormater.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
Note, when converting from the date string to a NSDate, you shouldn't quote the Z. If you quote the Z, it will match the literal Z character, but won't correctly reflect that this date string is actually Zulu/GMT/UTC.
If you want to create formatter that also goes the other way, converting NSDate objects to strings, in that case you should quote the Z, but in that case you must remember to explicitly set the timezone:
dateFormater.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
dateFormater.timeZone = NSTimeZone(forSecondsFromGMT: 0)
By the way, don't forget to set the locale as per Apple Technical Q&A 1480.
dateFormater.locale = NSLocale(localeIdentifier: "en_US_POSIX")

Resources