std::get_time is behaving in the same way when the format includes '%y' or '%Y', in both cases it tries to read a four digit year. Am I doing something wrong or is it a bug ?
Example code:
#include <iostream>
#include <iomanip>
void testDate(const char *format,const char *date)
{
std::istringstream ds(date);
std::tm tm = {};
ds >> std::get_time(&tm,format);
std::cout<<date<<" parsed using "<<format<<" -> Year: "<<tm.tm_year+1900<<" Month: "<<tm.tm_mon<<" Day: "<<tm.tm_mday<<std::endl;
}
int main()
{
testDate("%y%m%d","101112");
testDate("%Y%m%d","101112");
testDate("%y%m%d","20101112");
testDate("%Y%m%d","20101112");
return 0;
}
Output:
101112 parsed using %y%m%d -> Year: 1011 Month: 11 Day: 0
101112 parsed using %Y%m%d -> Year: 1011 Month: 11 Day: 0
20101112 parsed using %y%m%d -> Year: 2010 Month: 10 Day: 12
20101112 parsed using %Y%m%d -> Year: 2010 Month: 10 Day: 12
Tested with:
g++ (SUSE Linux) 11.2.1 20210816 [revision 056e324ce46a7924b5cf10f61010cf9dd2ca10e9]
clang++ version 12.0.1
Found after testing
%y - Enter only two digits
%Y - Enter only four digits
If you use 4 digits when using %y, then 4 digits will be output directly, if it is 2 digits, it is consistent with the document
The Month
The Month, From the std::tm
tm_mon : months since January – [0, 11]
so it print out 11 represents December. You can use below code to print out the date.
std::cout << std::put_time(&tm, "%c") << std::endl;
Related
I am working with a dataset that contains the following information: date and time in the form "yyyy-mm-dd", "hh:mm". It also contains the name of the US state where the time has been measured. My goal is to unify all the time measurements so that they are all in the UTC timezone. I have written a code that doesn't work and I don't intend to go through the details of that code. However, in order to check why my code doesn't work, I have written a simple test that also doesn't work. The test is as follows:
I have tried to convert "Friday January 1 2021 9:00 AM California" to its equivalent UTC time which is "Friday January 1 2021 5:00 PM". The code snippet for conversion comes in the following:
struct tm calTM;
calTM.tm_hour = 9;
calTM.tm_min = 0;
calTM.tm_year = 2021-1900;
calTM.tm_mon = 1-1;
calTM.tm_mday = 1;
calTM.tm_isdst = -1;
setenv("TZ", "America/California", 1);
time_t calTime = mktime(&calTM);
unsetenv("TZ");
struct tm* utcTime;
utcTime = gmtime(&calTime);
cout << "UTC hh: " << utcTime->tm_hour << ", UTC mm: " << utcTime->tm_min;
cout << ", UTC year: " << utcTime->tm_year << ", UTC month: " << utcTime->tm_mon << ", UTC day: " << utcTime->tm_mday << endl;
Instead of producing the expected result (Friday January 1 2021 5:00 PM), the code snippet above produces the following result:
UTC hh: 9, UTC mm: 0, UTC year: 121, UTC month: 0, UTC day: 1
which is "month 0, day 1, year 121, 9:00 AM". Year and month are fixed after passing utcTime to the mktime() function. After adding the lines
time_t utc_time_t = mktime(utcTime);
cout << ctime(&utc_time_t) << endl;
the output is
Fri Jan 1 09:00:00 2021
Still, the time (hh:mm:ss) is wrong (exactly the same as in the original timezone). Could you please help me figure out the problem with my code? Thank you very much!
quick question: why do I get a lot of zeros after the decimal point in the output of this script (value of "total" variable)? (I know how to deal with it and get specific outbut by walk-arounds, but I'm curious why thi iutput looks like this)
Script:
prices = {
"banana" : 4,
"apple" : 2,
"orange" : 1.5,
"pear" : 3,
}
stock = {
"banana" : 6,
"apple" : 0,
"orange" : 32,
"pear" : 15,
}
for key in prices:
print key
print "price: %s" % prices[key]
print "stock: %s" % stock[key]
print
total = 0
for iteration in prices:
total = total+ prices[iteration] * stock[iteration]
print "total price: %f"%total
output:
banana
price: 4
stock: 6
apple
price: 2
stock: 0
orange
price: 1.5
stock: 32
pear
price: 3
stock: 15
total price: 117.000000 #********* why so many zeros?
Because that's the default number of decimal places for the %f formatter.
Add a precision specifier; for example, if you only want to display 2 decimal places, use %.2f:
print "total price: %.2f" % total
and the last line of output then becomes
total price: 117.00
The . followed by a digit in the format specification signals the precision specifier. See the String Formatting Operations documentation:
A conversion specifier contains two or more characters and has the following components, which must occur in this order:
[...]
Precision (optional), given as a '.' (dot) followed by the precision. [...]
Further on in the same documentation, the default for f is documented under footnote #3:
The precision determines the number of digits after the decimal point and defaults to 6.
you must replace %f by %d or by %i if you dont want zeros and if you want 1 zero you can replace it by %s:
>>> print "total price: %d"%total
total price: 117
>>> print "total price: %s"%total
total price: 117.0
>>> print "total price: %f"%total # Like you did
total price: 117.000000
I have the following Swift (Swift 3) function to make a date (Date) with date components (DateComponents).
func makeDate(year: Int, month: Int, day: Int, hr: Int, min: Int, sec: Int) -> NSDate {
let calendar = NSCalendar(calendarIdentifier: .gregorian)!
let components = NSDateComponents()
components.year = year
components.month = month
components.day = day
components.hour = hr
components.minute = min
components.second = sec
let date = calendar.date(from: components as DateComponents)
return date! as NSDate
}
If I use it, it will return a GMT date.
override func viewDidLoad() {
super.viewDidLoad()
let d = makeDate(year: 2017, month: 1, day: 8, hr: 22, min: 16, sec: 50)
print(d) // 2017-01-08 13:16:50 +0000
}
What I actually want to return is a date (2017-01-08 22:16:50) literally based on those numbers. How can I do that with DateComponents? Thanks.
The function does return the proper date. It's the print function which displays the date in UTC.
By the way, the native Swift 3 version of your function is
func makeDate(year: Int, month: Int, day: Int, hr: Int, min: Int, sec: Int) -> Date {
var calendar = Calendar(identifier: .gregorian)
// calendar.timeZone = TimeZone(secondsFromGMT: 0)!
let components = DateComponents(year: year, month: month, day: day, hour: hr, minute: min, second: sec)
return calendar.date(from: components)!
}
But if you really want to have UTC date, uncomment the line to set the time zone.
NSDate doesn't know anything about time zones. It represents a point in time independent of any calendars or time zones. Only when printing it out like you did here it is converted to GMT. That's OK though - this is only meant for debugging. For real output use a NSDateFormatter to convert the date to a string.
As a hacky solution you might of course just configure your calendar to use GMT when creating your date object from your components. That way you will get the string you expect. Of course any other calculation with that date then might end up wrong.
I want to know to which quarter(Q1,Q2,Q3,Q4) does the current month belongs to in python. I'm fetching the current date by importing time module as follows:
import time
print "Current date " + time.strftime("%x")
any idea how to do it ?
Modifying your code, I get this:
import time
month = int(time.strftime("%m")) - 1 # minus one, so month starts at 0 (0 to 11)
quarter = month / 3 + 1 # add one, so quarter starts at 1 (1 to 4)
quarter_str = "Q" + str(quarter) # convert to the "Qx" format string
print quarter_str
Or you could use the bisect module:
import time
import bisect
quarters = range(1, 12, 3) # This defines quarters: Q1 as 1, 2, 3, and so on
month = int(time.strftime("%m"))
quarter = bisect.bisect(quarters, month)
quarter_str = = "Q" + str(quarter)
print quarter_str
strftime does not know about quarters, but you can calculate them from the month:
Use time.localtime to retrieve the current time in the current timezone. This function returns a named tuple with year, month, day of month, hour, minute, second, weekday, day of year, and time zone offset. You will only need the month (tm_mon).
Use the month to calculate the quarter. If the first quarter starts with January and ends with March, the second quarter starts with April and ends with June, etc. then this is as easy as dividing by 4 without remainder and adding 1 (for 1..3 // 4 == 0, 0 + 1 == 1, 4..6 // 4 == 1, 1 + 1 == 2, etc.). If your definition of what a quarter is differs (e.g. companies may choose different start dates for their financial quarters), you have to adjust the calculation accordingly.
I'm writing a script which calculates the date of Easter for years 1900 - 2099.
The thing is that for 4 certain years (1954, 1981, 2049, and 2076) the formula differs a little bet (namely, the date is off 7 days).
def main():
print "Computes the date of Easter for years 1900-2099.\n"
year = input("The year: ")
if year >= 1900 and year <= 2099:
if year != 2049 != 2076 !=1981 != 1954:
a = year%19
b = year%4
c = year%7
d = (19*a+24)%30
e = (2*b+4*c+6*d+5)%7
date = 22 + d + e # March 22 is the starting date
if date <= 31:
print "The date of Easter is March", date
else:
print "The date of Easter is April", date - 31
else:
if date <= 31:
print "The date of Easter is March", date - 7
else:
print "The date of Easter is April", date - 31 - 7
else:
print "The year is out of range."
main()
Exerything is working well but the 4 years computation.
I'm getting the:
if date <= 31:
UnboundLocalError: local variable 'date' referenced before assignment whenever I'm entering any of the 4 years as input.
You cannot chain a expression like that; chain the tests using and operators or use a not in expression instead:
# and operators
if year != 2049 and year != 2076 and year != 1981 and year != 1954:
# not in expression
if year not in (2049, 2076, 1981, 1954):
The expression year != 2049 != 2076 !=1981 != 1954 means something different, it is interpreted as (((year != 2049) != 2076) !=1981) != 1954 instead; the first test is either True or False, and neither of those two values will ever be equal to any of the other numbers and that branch will always evaluate to False.
You will still get the UnboundLocalError for date though, since your else branch refers to date but it is never set in that branch. When the else branch executes, all Python sees is:
def main():
print "Computes the date of Easter for years 1900-2099.\n"
year = input("The year: ")
if year >= 1900 and year <= 2099:
if False:
# skipped
else:
if date <= 31:
print "The date of Easter is March", date - 7
else:
print "The date of Easter is April", date - 31 - 7
and date is never assigned a value in that case. You need to calculate date separately in that branch still, or move the calculation of the date value out of the if statement altogether; I am not familiar with the calculation of Easter so I don't know what you need to do in this case.