Day month and year algorithm using Gettimeofday() in C [duplicate] - c++

This question already has answers here:
How can I convert seconds since the epoch to hours/minutes/seconds in Java?
(6 answers)
Closed 9 years ago.
Im required as part of a lab to devise a way to calculate the current month day and year. I'll be using the gettimeofday() function which gives me the number of seconds since january 1 1970.
I know that there are functions that will do the conversoins for me, however the design requirement is that i create my own algorithm for converting the seconds to months days and years. The manner in which I want to implement my design is with a lookup table for each of the twelve months and the corresponding number of days. The logic is a little befuddling to me right now.
The tricky part is handling the leap years. I know that 1972 is the first leap year since 1970. And a leap year occurs every 4 years since that date. The hint given to me in this assignment is that the next largest cycle after days is 4 years. So if I modulus the number of days since 1970 by 1461 (number of days in 4 years) I know I can get the number of days left over. Its at this point my train of logic gets lost. If I DIVIDE it by 1461 it just tells me the how many 4 year periods have gone by.
The table I want to implement will look something like this ( i know the coding isnt completely right but just to show what im getting at):
struct Monthdays
{
int days;
char* Monthname[]
};
Monthdays lookupMonths[]
{
{31,"January"}
{28,"February"}
.
.
.
};
Im trying to figure out how to create a proper index using the number of days or something to walk through this "table".........I hope asking this here is okay. I've been struggling with the logic or a couple of days right now....
Here is the code for this problem i have now which is very inefficient.
ExpandedTime* localTime(
struct timeval* tv, // Pointer to timeval struct
ExpandedTime* etime // '' '' to expandedtime strct
)
{
tzset(); // Corrects for timezone
int epochT = (tv->tv_sec) - timezone; // Epoch seconds with
int epochUT = tv->tv_usec; // epochtime microseconds
int edays; // Days since epochtime
etime->et_usec = (epochUT/milli) % milli; // Find the milliseconds
etime->et_sec = epochT % 60;
epochT /= 60; // Turn into minutes
etime->et_min = epochT % 60;
epochT /= 60; // Turn into hours
if (localtime(&tv->tv_sec)->tm_isdst !=0)
etime->et_hour = (epochT % 24) + daylight; // Hours with DST correc
else
etime->et_hour = (epochT % 24);
edays = epochT /= 24; // Turn into days
etime->et_day = epochT; // Delete up to here
etime->et_year = (epochT/365) + epochyear; // Get the current year
int trackyear; // Counter for years
int trackdays = -1; // Subtracting janurary 1st
// from days
// This will determine if it is a leapyear and adjust days accordingly
// from 1970 to current year (2013)
for (trackyear = epochyear; trackyear < etime->et_year; trackyear++)
{
if (trackyear % leapy == 0)
{
trackdays = trackdays + 366;
}
else
{
trackdays = trackdays + 365;
}
}
etime->et_day = edays - trackdays;
int trackmonth = -1; // Counter for months
// with offset to make
// january = 0
// This will give me the number of months for the buffer
do
{
switch (trackmonth)
{
// Months with 31 days
case 0:
etime->et_day = (etime->et_day) - 31;
break;
case 2:
etime->et_day = (etime->et_day) - 31;
break;
case 4:
etime->et_day = (etime->et_day) - 31;
break;
case 6:
etime->et_day = (etime->et_day) - 31;
break;
case 7:
etime->et_day = (etime->et_day) - 31;
break;
case 9:
etime->et_day = (etime->et_day) - 31;
break;
case 11:
etime->et_day = (etime->et_day) - 31;
break;
// Months with only 30 days
case 3:
etime->et_day = (etime->et_day) - 30;
break;
case 5:
etime->et_day = (etime->et_day) - 30;
break;
case 8:
etime->et_day = (etime->et_day) - 30;
break;
case 10:
etime->et_day = (etime->et_day) - 30;
break;
// Leap year month a.k.a Febuary
case 1:
if (trackyear % leapy)
{
etime->et_day = (etime->et_day) - 28;
}
else
{
etime->et_day = (etime->et_day) - 29;
}
break;
}
trackmonth++;
}
while(etime->et_day > 0);
etime->et_mon = trackmonth - 1;
// Reverts day offset from previous switch to
// accurately represent the current day
switch (etime->et_mon)
{
// Months with 31 days
case 0:
etime->et_day = (etime->et_day) + 31;
break;
case 2:
etime->et_day = (etime->et_day) + 31;
break;
case 4:
etime->et_day = (etime->et_day) + 31;
break;
case 6:
etime->et_day = (etime->et_day) + 31;
break;
case 7:
etime->et_day = (etime->et_day) + 31;
break;
case 9:
etime->et_day = (etime->et_day) + 31;
break;
case 11:
etime->et_day = (etime->et_day) + 31;
break;
// Months with only 30 days
case 3:
etime->et_day = (etime->et_day) + 30;
break;
case 5:
etime->et_day = (etime->et_day) + 30;
break;
case 8:
etime->et_day = (etime->et_day) + 30;
break;
case 10:
etime->et_day = (etime->et_day) + 30;
break;
// Leap year month a.k.a Febuary
case 1:
if (trackyear % leapy)
{
etime->et_day = (etime->et_day) + 28;
}
else
{
etime->et_day = (etime->et_day) + 29;
}
break;
}
return etime;
}

Do a little web surfing for information on how to calculate a Julian Date (or more precisely a Julian Day Number) ... that will solve your problem or get you well on your way.
Other than that, it would be unethical to do someone's homework for them... though... I do have a PayPal account ~lol~

if(year % 4 == 0 && year % 100 == 0 && year % 25 != 0)
this is a leap year.
This was actually the hardest kind of homework i had on college... all in all, depending on how accurate this needs to be, i'll tell you to [not] look into timezones and when different zones enter daylight savings...
Sorry if the answer isn't terribly helpful, but this is the formula for leap years. If you keep going the route you're headed, you'll need to bring in the Chinese theorem into this...
But if you can do gettimeofday() it returns the number of milliseconds since 1st January 1970. So you can just put a little for in it that will 'waste' the seconds and simulate passage of time up until now, and run that loop until you run out of time. When you stop you should be able to see at which date you stopped ;)

Related

Input a date in 8 digit numerical form and display into English form

Below is the c++ problem i have to solve and i'm having some trouble from number 2)
1) Prompt the user to input a date in 8 digit numerical form(MMDDYYYY)
ex. 04221970
2) Display the date in English form
ex. 22nd April 1970
3) If the day the user entered is 01,21,31, add "st" after the day
4) Else if the day the user entered is 02,22, add "nd" after the day
5) Elae if the day user entered is 03,23, add "rd" after the day
6) Else add "th" after the day
All of the step are rather straightforward. But dates are always tricky, since there are many rules. But only a couple apply for parsing.
Define a struct to hold the parsed value and parse the input.
[EDIT] The value of using a struct, is that it can be useful to have an intermediate function that would return this reusable bit of binary data.
struct date_s
{
unsigned int day;
unsigned int month;
unsigned int year;
};
// parsing
date_s date = {};
if (strlen(input) != 8 || sscanf(input, "%2u%2u%4u", &date.month, &date.day, &date.year) != 3)
{
// handle error
}
Validating the year is rather easy, there is nothing to do, unless you want to restrict to a specific range. For example, since we're using the Gregorian calendar, you may want to restrict to years after 1582, inclusive.
Validating the month is also very straightforward, we'll validate that along with the number of days in a month, which is the most tricky part, because of Febuary.
unsigned int day_max = 0;
switch (date.month)
{
case 1: case 3: case 5; case 7: case 8: case 10: case 12:
day_max = 31;
break;
case 4: case 6: case 9: case 11:
day_max = 30;
break;
case 2:
if (date.year % 4 != 0)
day_max = 28;
else if (date.year % 100 != 0)
day_max = 29;
else if (date.year % 400 != 0)
day_max = 28;
else
day_max = 29;
break;
// else day_max stays 0, of course
}
if (date.day < 1 || day_max < date.day)
{
// error
}
After all the validating is done, all you have to do is print.
For the months you will need to define a table of strings for display.
const char* MONTH[12] = { "January", /* etc... */ };
Date suffix.
const char* SUFFIX[4] = { "st", "nd", "rd", "th" };
We now have all the data we need to print, and all within range, too.
const char* suffix = SUFFIX[std::min(date.day, 4) - 1];
printf("%d%s %s %d", date.day, suffix, MONTH[date.month - 1], date.year);
// or, for US format
printf("%s %d%s, %d", MONTH[date.month - 1], date.day, suffix, date.year);

How to loop a switch statement until desired number is found?

cout<<"========================================="<<endl<<endl;
cout<<"The amount you need to pay is RM "<<total<<endl;
cout<<"=========================================="<<endl<<endl;
cout<<"You can pay using ($0.10 [1] $0.20 [2] $0.50 [3] $1 [4] $5 [5] $10 [6] $20 [7] $50 [8] )"<<endl;
cin>>choice2;
switch(choice2){
case 1:
total = total - 0.10;
break;
case 2:
total = total - 0.20;
break;
case 3:
total = total - 0.50;
break;
case 4:
total = total - 1;
break;
case 5:
total = total - 5;
break;
case 6:
total = total - 10;
break;
case 7:
total = total - 20;
break;
case 8:
total = total - 50;
break;
default:
cout<<"inavalid!"<<endl;
}
if(total > 0){
cout<<"you still need to pay "<<total<<endl;
cin>>choice2;
}
Extra information: My total is $5
I am trying to let it loop until the total amount is paid, say I choose case 4 which is $1. It's suppose to let me insert the remaining amount I am supposed to pay, which is $4, but the program ends after I insert another switch case option.
This part, isn't it supposed to be looping until my total is 0?
if(total > 0){
cout<<"you still need to pay "<<total<<endl;
cin>>choice2;
}
Thanks in advance for any help, I am also happy to learn any shorter way of writing this program if there is any, also is there anyway I can implement array into this program?
No, neither the switch nor the if will cause your program to loop.
You're probably looking for something along the lines of
while(total > 0)
{
cin>>choice2;
switch(choice2){
// left out for clarity
}
if(total > 0){
cout<<"you still need to pay "<<total<<endl;
//Instead of getting the input in 2 different locations, just get it again at the start of the next loop.
}
}

How to get the right value?

What must I do to get the right Level?
example:
int gXP = globalDoHandle::PlayerStats_XP(p);
ostringstream sXP; sXP << "XP(RP): " << gXP;
ostringstream sLEVEL; sLEVEL << "Level: " << gLEVEL;
I want use the XP value to get the right Level then.
If I get the the value 24450 should give me it then "10" back
I know I can use something like this, but that are 8000 Level in the Game!
if (gXP < 800) { Rank = "1"; }
else if (gXP < 2100) { Rank = "2"; }
else if (gXP < 3800) { Rank = "3"; }
...
LEVEL: XP
Level 1: 0
Level 2: 800
Level 3: 2100
Level 4: 3800
Level 5: 6100
Level 6: 9500
Level 7: 12500
Level 8: 16000
Level 9: 19800
Level 10: 24000
Level 11: 28500
Level 12: 33400
Level 13: 38700
Level 14: 44200
Level 15: 50200
Level 16: 56400
Level 17: 63000
Level 18: 69900
Level 19: 77100
Level 20: 84700
...Level 8000: 1787576850
To do such a job, you need std::lower_bound. std::lower_bound(l, h, v) returns an iterator it inside the range [l, h) for which the value on the range is the smallest verifying *it > v.
constexpr std::array<unsigned, 10> levels = { /* ... */ }; // xp needed for each level
unsigned level(unsigned xp)
{
auto it = std::lower_bound(cbegin(levels), cend(levels), xp);
return std::distance(begin(levels), it);
}
level(xp) returns the level reached with xp experience points with respect to the values of levels.
Se a full demo online
Use a std::array with your exp values in.
std::array<int, 8000> exp_table = { 0, 800, 2100... };
int level=0;
for(; level < exp_table.size() && exp_table[level] < gXP; ++level);
Rank = std::to_string(level); // If this is needed?
After this level will be set correctly. The only thing left is how you generate your exp_table. Read it from a file. Use some math formula.

Convert OLE Automation Date (OADate) double to struct tm without using VariantTimeToSystemTime

I'm writing a Windows DLL in mostly std C++ (VS2010), which does not use MFC/ATL.
A parent module does use MFC and passes a COleDateTime.m_dt to my DLL, which arrives as a double. I believe this is an OLE Automation Date, also known as OADate.
I want to convert this to any type of standard struct (tm...) that has days, hours, etc without pulling MFC, OLE, etc into my DLL.
This has been asked before (Convert Date/Time (as Double) to struct* tm in C++) however, the answer is always using VariantTimeToSystemTime(), which misses the point of that question - not using MFC / OLE, etc.
VariantTimeToSystemTime's requirements are:
Header - OleAuto.h
Library - OleAut32.lib
DLL - OleAut32.dll
My DLL has basically no dependencies at the moment, so I would prefer not to pull OleAut32.dll in for this one conversion.
The best thing I've found so far has been this C# mono code, which I may convert to C++.
I have 2 solutions, the first is working with a function that implements gmtime_r so that this solution will don't use any standard functions. The second solution is using the standard function gmtime_r.
1. First solution: Own implementation of gmtime_r (01-Jan-1601 to 31-Dec-9999):
It will work for dates between 01-Jan-1601 and 31-Dec-9999. I've implemented a fromOADate function which uses the SecondsSinceEpochToDateTime function from this answer on SO wich converts seconds before or after 01-Jan-1970 to a tm structure but works only from 01-Jan-1601 on.
I changed the function from that answer to work also with 32 bit by adding one ULL suffix. That requires that the long long types are 64 bit wide, if that's not the case this solution will not work.
If you need dates before year 1601 you could change the SecondsSinceEpochToDateTime as it is well documentated.
To test different values this online conversion is very nice which also supports unix timestamp and the OADate type.
Full working code and example on ideone:
#include <iostream>
#include <ctime>
#include <cstring>
struct tm* SecondsSinceEpochToDateTime(struct tm* pTm, uint64_t SecondsSinceEpoch)
{
uint64_t sec;
unsigned int quadricentennials, centennials, quadrennials, annuals/*1-ennial?*/;
unsigned int year, leap;
unsigned int yday, hour, min;
unsigned int month, mday, wday;
static const unsigned int daysSinceJan1st[2][13]=
{
{0,31,59,90,120,151,181,212,243,273,304,334,365}, // 365 days, non-leap
{0,31,60,91,121,152,182,213,244,274,305,335,366} // 366 days, leap
};
/*
400 years:
1st hundred, starting immediately after a leap year that's a multiple of 400:
n n n l \
n n n l } 24 times
... /
n n n l /
n n n n
2nd hundred:
n n n l \
n n n l } 24 times
... /
n n n l /
n n n n
3rd hundred:
n n n l \
n n n l } 24 times
... /
n n n l /
n n n n
4th hundred:
n n n l \
n n n l } 24 times
... /
n n n l /
n n n L <- 97'th leap year every 400 years
*/
// Re-bias from 1970 to 1601:
// 1970 - 1601 = 369 = 3*100 + 17*4 + 1 years (incl. 89 leap days) =
// (3*100*(365+24/100) + 17*4*(365+1/4) + 1*365)*24*3600 seconds
sec = SecondsSinceEpoch + 11644473600ULL;
wday = (uint)((sec / 86400 + 1) % 7); // day of week
// Remove multiples of 400 years (incl. 97 leap days)
quadricentennials = (uint)(sec / 12622780800ULL); // 400*365.2425*24*3600
sec %= 12622780800ULL;
// Remove multiples of 100 years (incl. 24 leap days), can't be more than 3
// (because multiples of 4*100=400 years (incl. leap days) have been removed)
centennials = (uint)(sec / 3155673600ULL); // 100*(365+24/100)*24*3600
if (centennials > 3)
{
centennials = 3;
}
sec -= centennials * 3155673600ULL;
// Remove multiples of 4 years (incl. 1 leap day), can't be more than 24
// (because multiples of 25*4=100 years (incl. leap days) have been removed)
quadrennials = (uint)(sec / 126230400); // 4*(365+1/4)*24*3600
if (quadrennials > 24)
{
quadrennials = 24;
}
sec -= quadrennials * 126230400ULL;
// Remove multiples of years (incl. 0 leap days), can't be more than 3
// (because multiples of 4 years (incl. leap days) have been removed)
annuals = (uint)(sec / 31536000); // 365*24*3600
if (annuals > 3)
{
annuals = 3;
}
sec -= annuals * 31536000ULL;
// Calculate the year and find out if it's leap
year = 1601 + quadricentennials * 400 + centennials * 100 + quadrennials * 4 + annuals;
leap = !(year % 4) && (year % 100 || !(year % 400));
// Calculate the day of the year and the time
yday = sec / 86400;
sec %= 86400;
hour = sec / 3600;
sec %= 3600;
min = sec / 60;
sec %= 60;
// Calculate the month
for (mday = month = 1; month < 13; month++)
{
if (yday < daysSinceJan1st[leap][month])
{
mday += yday - daysSinceJan1st[leap][month - 1];
break;
}
}
// Fill in C's "struct tm"
memset(pTm, 0, sizeof(*pTm));
pTm->tm_sec = sec; // [0,59]
pTm->tm_min = min; // [0,59]
pTm->tm_hour = hour; // [0,23]
pTm->tm_mday = mday; // [1,31] (day of month)
pTm->tm_mon = month - 1; // [0,11] (month)
pTm->tm_year = year - 1900; // 70+ (year since 1900)
pTm->tm_wday = wday; // [0,6] (day since Sunday AKA day of week)
pTm->tm_yday = yday; // [0,365] (day since January 1st AKA day of year)
pTm->tm_isdst = -1; // daylight saving time flag
return pTm;
}
struct tm* fromOADate(struct tm* p_Tm, double p_OADate)
{
static const int64_t OA_UnixTimestamp = -2209161600; /* 30-Dec-1899 */
if (!( -109205 <= p_OADate /* 01-Jan-1601 */
&& p_OADate <= 2958465)) /* 31-Dec-9999 */
{
throw std::string("OADate must be between 109205 and 2958465!");
}
int64_t OADatePassedDays = p_OADate;
double OADateDayTime = p_OADate - OADatePassedDays;
int64_t OADateSeconds = OA_UnixTimestamp
+ OADatePassedDays * 24LL * 3600LL
+ OADateDayTime * 24.0 * 3600.0;
return SecondsSinceEpochToDateTime(p_Tm, OADateSeconds);
}
int main()
{
struct tm timeVal;
std::cout << asctime(fromOADate(&timeVal, -109205)); /* 01-Jan-1601 00:00:00 */
std::cout << asctime(fromOADate(&timeVal, 0)); /* 30-Dec-1899 00:00:00 */
std::cout << asctime(fromOADate(&timeVal, 25569)); /* 01-Jan-1970 00:00:00 */
std::cout << asctime(fromOADate(&timeVal, 50424.134803241)); /* 19-Jan-2038 03:14:07 */
std::cout << asctime(fromOADate(&timeVal, 2958465)); /* 31-Dec-9999 00:00:00 */
return 0;
}
2. Second solution: Using gmtime_r (01-Jan-1970 to 19-Jan-2038/31-Dec-9999 (32/64 bit)):
As already said this solution has not that wide range as the variant from above but just uses a standard function (full working example at ideone):
#include <iostream>
#include <ctime>
struct tm* fromOADate(struct tm* p_Tm, double p_OADate)
{
static const int64_t OA_UnixTimestamp = -2209161600; /* 30-Dec-1899 */
if (!( 25569 <= p_OADate /* 01-Jan-1970 00:00:00 */
&& p_OADate <= 2958465)) /* 31-Dec-9999 00:00:00 */
{
throw std::string("OADate must be between 25569 and 2958465!");
}
time_t OADatePassedDays = p_OADate;
double OADateDayTime = p_OADate - OADatePassedDays;
time_t OADateSeconds = OA_UnixTimestamp
+ OADatePassedDays * 24LL * 3600LL
+ OADateDayTime * 24.0 * 3600.0;
/* date was greater than 19-Jan-2038 and build is 32 bit */
if (0 > OADateSeconds)
{
throw std::string("OADate must be between 25569 and 50424.134803241!");
}
return gmtime_r(&OADateSeconds, p_Tm);
}
int main()
{
struct tm timeVal;
std::cout << asctime(fromOADate(&timeVal, 25569)); /* 01-Jan-1970 00:00:00 */
std::cout << asctime(fromOADate(&timeVal, 50424.134803241)); /* 19-Jan-2038 03:14:07 */
return 0;
}

Is jBCrypt's default log_rounds still appropriate for 2013

I've been using jBCrypt version 0.3 out-of-the-box now since it came out in 2010. I use the default getsalt() method which sets the number of "log_rounds" to 10. Given the progression of password cracking hardware and methods, is this value still appropriate as a default, or should i be looking at some higher value.
Info from the javadoc...
String pw_hash = BCrypt_v03.hashpw(plain_password, BCrypt_v03.gensalt());
String strong_salt = BCrypt_v03.gensalt(10)
String stronger_salt = BCrypt_v03.gensalt(12)
The amount of work increases exponentially (2**log_rounds), so each increment is twice as much work. The default log_rounds is 10, and the valid range is 4 to 31.
I made a little test class to check the performance of checkPw() under differing salt log_rounds.
public void testCheckPerformance() {
int MULT = 1;
for( int i = 4; i < 31; i++) {
String salt = BCrypt_v03.gensalt(i);
String hashpw = BCrypt_v03.hashpw("my pwd", salt);
long startTs = System.currentTimeMillis();
for( int mult = 0; mult < MULT; mult++) {
assertTrue(BCrypt_v03.checkpw("my pwd", hashpw));
}
long endTs = System.currentTimeMillis();
System.out.println(""+i+": " + ((endTs-startTs)/MULT));
}
}
My PC is an 8 core i7 2.8GHz. The results are:
log-rounds: time in millis.
4: 3
5: 3
6: 6
7: 11
8: 22
9: 46
10: 92
11: 188
12: 349
13: 780
14: 1449
15: 2785
16: 5676
17: 11247
18: 22264
19: 45170
Using the default log_rounds=10 means that a single thread can check a login in 0.1s. This potentially limits the number of login checks per second that a single server can achieve.
So i guess the question becomes how much time are you prepared to spend per password check vs how many password checks per second you want to size the system to cope with.