How to get following DateTime in Erlang?
Fri Jul 13 19:12:59 IST 2018
TL; DR
Use the exceptional qdate for all your date/time formatting, converting, and timezone handling. Look at the Demonstration section in particular to get the gist, and adjust to your needs.
Erlang's date handling, in my opinion, is convoluted and lacking in the major functionality that's needed for proper date handling. It's getting better, but not quite there. Moreover, timezone handling is primitive at best.
qdate's functions will take (almost) any date format and convert to any date format, while using either an implicit timezone (setting the timezone on a per-process basis), or by setting a specific timezone.
In any case, if you go custom, you will end up with something similar to this:
1> {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:now_to_datetime(erlang:now()).
{{2018,7,13},{14,39,45}}
2> lists:flatten(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w",[Year,Month,Day,Hour,Minute,Second])).
"2018-07-13T14:39:45"
...not good ;)
Those are my two cents. Cheers!
I found the solution.
A = calendar:universal_time().
qdate:to_string(<<"D M j G:i:s T Y">> , <<"IST">>, A).
You can use http://uk3.php.net/manual/en/function.date.php for different formatting. Advisable to use only if you have to support legacy system because this function call use seems expensive.
date_time() ->
{{Year, Month, Day},{ Hour, Minute, Second}} = calendar:local_time(),
DayOfWeek = calendar:day_of_the_week({Year, Month, Day}),
DayName = day_check(DayOfWeek),
MonthName = month_check(Month),
lists:flatten(io_lib:format("~3..0s ~3..0s ~2..0w ~2..0w:~2..0w:~2..0w IST ~4..0w", [DayName, MonthName, Day, Hour, Minute, Second, Year])).
day_check(1) -> 'Mon';
day_check(2) -> 'Tue';
day_check(3) -> 'Wed';
day_check(4) -> 'Thu';
day_check(5) -> 'Fri';
day_check(6) -> 'Sat';
day_check(7) -> 'Sun'.
month_check(1) -> 'Jan';
month_check(2) -> 'Feb';
month_check(3) -> 'Mar';
month_check(4) -> 'Apr';
month_check(5) -> 'May';
month_check(6) -> 'Jun';
month_check(7) -> 'Jul';
month_check(8) -> 'Aug';
month_check(9) -> 'Sep';
month_check(10) -> 'Oct';
month_check(11) -> 'Nov';
month_check(12) -> 'Dec'.
Related
I want to get the current time, and format it in the following way:
yyyy-MM-dd'T'HH:mm:ss.SSSZ
(where SSS is the milliseconds and Z the time zone)
the code so far I have it as follows:
formatted_date() ->
{{Y,M,D},{H,Min,S}} = erlang:localtime(),
{Ms, _, _} = os:timestamp(),
{Days, {Hours, _,_}} = calendar:time_difference(erlang:universaltime(), erlang:localtime()),
Difference = 24*Days + Hours,
Tz = [case Difference < 0 of
true ->
$-;
false ->
$+
end | io_lib:format("~2..0B00",[Difference])],
io_lib:format("[~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B.~3..0B ~5.s]",
[Y, M, D, H, Min, S, Ms, Tz]).
The fact is that it always returns the same Ms, therefore, I think that I am not doing it well, and in other questions I only see how to obtain the total time in milliseconds, but not how to format it in this way.
Thank you.
The easiest way is to use the library function calendar:system_time_to_rfc3339/2 - it seems to fulfil all your requirements.
> calendar:system_time_to_rfc3339(os:system_time(millisecond), [{unit, millisecond}]).
"2021-03-03T18:42:08.497+05:30"
This function was added in Erlang/OTP 21.0, which was released in June 2018.
The reason your code always gets the same value for Ms is that the first value in the tuple returned by os:timestamp/0 is megaseconds, not milliseconds; the three values are megaseconds, seconds and microseconds. This comes from a time when Erlang did not support large integers, so splitting up the timestamp was necessary. These days you can just call os:system_time/1 or a number of other functions, depending on what kind of time you need, and get the result in a single integer.
I am parsing JSON data from a server, which I can set to 'UK' or 'Asia'
Function:
func dateToStringConverter(jsonDate: String) -> String {
let isoDate = jsonDate
let dateFormatter = ISO8601DateFormatter()
let processedDate = dateFormatter.date(from:isoDate)!
return processedDate.asString()}
Extension:
extension Date {
func asString() -> String {
let template = "EEEEd MMMM, h:mm a"
let formatter = DateFormatter()
let format = DateFormatter.dateFormat(fromTemplate: template, options: 0, locale: NSLocale.current)
formatter.dateFormat = format
return formatter.string(from: self)}}
print(dateToStringConverter(jsonDate: jsonDate))
Then, the following attribute from the server differs based on if I set 'UK or 'Asia':
let jsonDate = "2020-10-05T02:15:00+08:00" // server set to Asia
let jsonDate = "2020-10-04T19:15:00+01:00" // server set to UK
However, BOTH these values result in the SAME OUTPUT from the print statement!
Sunday, October 4, 7:15 PM
I believe what is happening here is, even if I set the server to Asia, Swift knows I am in the UK, and therefore prints Sunday, October 4, 7:15 PM
Is this correct?
If so, is there any way to mimic what print statement from Asia would see? I have tried changing the region in the simulator, but this didn't seem to make a difference
Thanks
The good thing about zoned ISO 8601 timestamps is that they represent a specific moment in UTC time. They do not contain information about which time zone they're from, as this is highly ambiguous. If you aim for easier human comparability, understandability and a reduction in ambiguity, I suggest going for UTC time.
In stead of
2020-01-01T02:00:00+01:00
you'd have
2020-01-01T01:00:00Z
Z is a shortcut for +00:00
When it ends in Z, it's always UTC time and thus easily comparable.
I need time since Epoch in ms for an API request, so I'm looking to have a function that converts my myUIDatePicker.date.timeIntervalSince1970 into milliseconds by multiplying by 1000. My question is what should the return value be?
Right now I have
func setTimeSinceEpoch(datePicker: UIDatePicker) -> Int {
return Int(datePicker.date.timeIntervalSince1970 * 1000)
}
Will this cause any issues? I need an integer, not a floating point, but will I have issues with overflow? I tested it out with print statements and it seems to work but I want to find the best way of doing this.
Looking at Apple Docs:
var NSTimeIntervalSince1970: Double { get }
There is a nice function called distantFuture. Even if you use this date in you func the result will be smaller then the max Int.
let future = NSDate.distantFuture() // "Jan 1, 4001, 12:00 AM"
print((Int(future.timeIntervalSince1970) * 1000) < Int.max) // true
So, until 4001 you're good to go. It will work perfectly on 64-bits systems.
Note: If your system supports iPhone 5 (32-bits) it's going to get an error on pretty much any date you use. Int in Iphone 5 corresponds to Int32.
Returning an Int64 is a better approach. See this.
im burning my brains trying to make a function that gives me the ammount of days between todays date and a given date.
possible today function:
today = fmap (formatTime defaultTimeLocale "%Y-%m-%d") getCurrentTime
and thought using diffDays, but wont be able to make it work with a ::Day date
any ideas?
Your formatTime version returns a string, but you want a Day (which looks like your string when you inspect it, but is a different type entirely). Here's one way to write a today function, using utctDay to get a Day out of a UTCTime:
import Data.Time.Calendar
import Data.Time.Clock
today :: IO Day
today = fmap utctDay getCurrentTime
And here's a days-from-today function (which I gave the shorter name daysAway) that uses it:
daysAway :: Day -> IO Integer
daysAway day = fmap (diffDays day) today
If you're always specifying the target as a calendar date, you can do that easily enough:
daysToDate :: Integer -> Int -> Int -> IO Integer
daysToDate year month day = daysAway $ fromGregorian year month day
Given a shorthand function for a commonly-needed relative day:
tomorrow :: IO Day
tomorrow = fmap (addDays 1) today
We can demonstrate the correctness of Annie's Thesis:
ghci> tomorrow >>= daysAway
1
I use SimpleXml in perl to extract data in tag
<description><strong>CUSIP:</strong> 912828UC2<br /><strong>Term and Type:</strong> 3-Year Note<br /><strong>Offering Amount:</strong> $32,000,000,000<br /><strong>Auction Date:</strong> 12/11/2012<br /><strong>Issue Date:</strong> 12/17/2012<br /><strong>Maturity Date:</strong> 12/15/2015<br /><a href="http://www.treasurydirect.gov/instit/annceresult/press/preanre/2012/A_20121206_6.pdf">PDF version of the announcement</a><br /><a href="http://www.treasurydirect.gov/xml/A_20121206_6.xml">XML version of the announcement</a><br /></description>
I now have trouble extracting individual symbols. For example for Auction Date, use
if ($desc=~m/Auction\sDate:<\/strong>\s+(\d\d\/\d\d\/\d\d\d\d)<br/)
{
}
but I feel it's not robust enough. What is the standard way to extract fields?
As Dan1111 points out in his answer, if you're already using an XML parser (Simple::XML?) you should stick with it for parsing the data within your description tags. It isn't a good idea to attempt to parse data out of an XML/HTML feed; use a parser built for that purpose.
Because of the formatting of the data in your post, I am assuming that you don't have valid HTML that a parser can help you with. In this case, there's no 'standard' way to extract fields, but here's the way I'd approach this problem:
print "$desc\n";
my #parts = split(/;br /, $desc);
my %dates;
foreach my $part (#parts) {
if ($part =~ m/(\w+\s+Date).+(\d{2}\/\d{2}\/\d{4})/) {
$dates{$1} = $2;
}
}
foreach my $label (keys %dates) {
printf "%-16s%12s\n", "${label}:", $dates{$label};
}
Looking at the original string, I can see that there are 3 dates, and several other records, so the first thing to do is to split them up. I found that each record in the string is delimited by the characters ';br ', so I used that for the split:
my #parts = split(/;br /, $desc);
After doing that, I have an array that contains each of the different data parts from your string. now, I just needed to parse each part. because your question is interested in the Auction Date value, I wrote a regular expression that will capture the date. anticipating that the other dates might be valuable as well, I modified my regex so that I could capture the label (Auction, Issue, Maturity), and I stored each label-date pair in a hash (%dates) :
foreach my $part (#parts) {
if ($part =~ m/(\w+\s+Date).+(\d{2}\/\d{2}\/\d{4})/) {
$dates{$1} = $2;
}
}
Finally, I just printed out my hash:
foreach my $part (#parts) {
if ($part =~ m/(\w+\s+Date).+(\d{2}\/\d{2}\/\d{4})/) {
$dates{$1} = $2;
}
}
Make sense?
What is more robust depends on your expected input and what you are looking for. However, here is something that you might find helpful.
I used XML::Twig for this. XML::Simple (which I assume is what you are using now) is not recommended for new development due to various quirks.
use Modern::Perl;
use XML::Twig;
my $twig = XML::Twig->new();
$twig->parse(<DATA>);
my %params;
my $key;
for my $child (map {$_->text} $twig->root->children)
{
if ($child =~ /(.*):/)
{
$key = $1;
}
else
{
$params{$key} = $child if (defined $key);
undef $key;
}
}
say "$_ is $params{$_}" foreach (keys %params);
__DATA__
<description><strong>CUSIP:</strong> 912828UC2<br /><strong>Term and Type:</strong> 3-Year Note<br /><strong>Offering Amount:</strong> $32,000,000,000<br /><strong>Auction Date:</strong> 12/11/2012<br /><strong>Issue Date:</strong> 12/17/2012<br /><strong>Maturity Date:</strong> 12/15/2015<br />PDF version of the announcement<br />XML version of the announcement<br /></description>
This takes any element that ends with a colon as a key, then assumes the next element in the tree is the value. Obviously that makes some assumptions of what kind of input you will get, but it is pretty robust as long as all of the "key" elements will be enclosed in tags.
Another approach would be stripping out all of the tags first, then searching for key-value pairs in just the text. You can do this with XML::Twig as well; simply calling $twig->root->text will get the text from the entire element. However, in this approach it would be tricky to determine where one key ends and another value begins.
The <description> elements in the RSS feed you show contain valid XHTML fragments as PCDATA. This solution extracts those elements and decodes them, and parses them in turn to access the text of the <strong> elements and their corresponding values.
Note that the XHTML contains multiple elements, and as XHTML is allowed only a single root element I have wrapped it in a dummy <root> elements in $twig->parse("<root>$desc</root>").
Hopefully you will be able to extrapolate from this to access the data you require.
use strict;
use warnings;
use LWP::Simple;
use XML::Twig;
my $xml = get 'http://www.treasurydirect.gov/RI/TreasuryOfferingAnnouncements.rss';
my $twig = XML::Twig->new;
$twig->parse($xml);
for my $desc ($twig->get_xpath('/rss/channel/item/description')) {
$desc = $desc->text;
my $twig = XML::Twig->new;
$twig->parse("<root>$desc</root>");
for my $strong ($twig->get_xpath('/root/strong')) {
my ($key, $val) = ($strong->trimmed_text, $strong->next_sibling->trimmed_text);
$key =~ s/:$//;
print "$key => $val\n";
}
print "\n";
}
output
CUSIP -> 912810QY7
Term and Type -> 29-Year 11-Month Bond
Offering Amount -> $13,000,000,000
Auction Date -> 12/13/2012
Issue Date -> 12/17/2012
Maturity Date -> 11/15/2042
CUSIP -> 912796DT3
Term and Type -> 3-Day Bill
Offering Amount -> $10,000,000,000
Auction Date -> 12/13/2012
Issue Date -> 12/14/2012
Maturity Date -> 12/17/2012
CUSIP -> 912828UE8
Term and Type -> 5-Year Note
Offering Amount -> $35,000,000,000
Auction Date -> 12/18/2012
Issue Date -> 12/31/2012
Maturity Date -> 12/31/2017
CUSIP -> 912828UD0
Term and Type -> 2-Year Note
Offering Amount -> $35,000,000,000
Auction Date -> 12/17/2012
Issue Date -> 12/31/2012
Maturity Date -> 12/31/2014
CUSIP -> 912796AM1
Term and Type -> 26-Week Bill
Offering Amount -> $28,000,000,000
Auction Date -> 12/17/2012
Issue Date -> 12/20/2012
Maturity Date -> 06/20/2013
CUSIP -> 912828UF5
Term and Type -> 7-Year Note
Offering Amount -> $29,000,000,000
Auction Date -> 12/19/2012
Issue Date -> 12/31/2012
Maturity Date -> 12/31/2019
CUSIP -> 912828SQ4
Term and Type -> 4-Year 4-Month TIPS
Offering Amount -> $14,000,000,000
Auction Date -> 12/20/2012
Issue Date -> 12/31/2012
Maturity Date -> 04/15/2017
CUSIP -> 9127957M7
Term and Type -> 13-Week Bill
Offering Amount -> $32,000,000,000
Auction Date -> 12/17/2012
Issue Date -> 12/20/2012
Maturity Date -> 03/21/2013
CUSIP -> 912828TY6
Term and Type -> 9-Year 11-Month Note
Offering Amount -> $21,000,000,000
Auction Date -> 12/12/2012
Issue Date -> 12/17/2012
Maturity Date -> 11/15/2022
CUSIP -> 912828UC2
Term and Type -> 3-Year Note
Offering Amount -> $32,000,000,000
Auction Date -> 12/11/2012
Issue Date -> 12/17/2012
Maturity Date -> 12/15/2015
CUSIP -> 912796AK5
Term and Type -> 52-Week Bill
Offering Amount -> $25,000,000,000
Auction Date -> 12/11/2012
Issue Date -> 12/13/2012
Maturity Date -> 12/12/2013
CUSIP -> 9127955V9
Term and Type -> 4-Week Bill
Offering Amount -> $40,000,000,000
Auction Date -> 12/11/2012
Issue Date -> 12/13/2012
Maturity Date -> 01/10/2013
CUSIP -> 912796AL3
Term and Type -> 26-Week Bill
Offering Amount -> $28,000,000,000
Auction Date -> 12/10/2012
Issue Date -> 12/13/2012
Maturity Date -> 06/13/2013
CUSIP -> 9127957L9
Term and Type -> 13-Week Bill
Offering Amount -> $32,000,000,000
Auction Date -> 12/10/2012
Issue Date -> 12/13/2012
Maturity Date -> 03/14/2013
CUSIP -> 912796DT3
Term and Type -> 11-Day Bill
Offering Amount -> $25,000,000,000
Auction Date -> 12/04/2012
Issue Date -> 12/06/2012
Maturity Date -> 12/17/2012
CUSIP -> 9127956Z9
Term and Type -> 4-Week Bill
Offering Amount -> $40,000,000,000
Auction Date -> 12/04/2012
Issue Date -> 12/06/2012
Maturity Date -> 01/03/2013